Skip to content

Commit a9ae734

Browse files
committed
[lldb-dap] Refactoring IOStream into Transport handler.
Instead of having two discrete InputStream and OutputStream helpers, this merges the two into a unifed 'Transport' handler. This handler is responsible for reading the DAP message headers, parsing the resulting JSON and converting the messages into `lldb_dap::protocol::Message`s for both input and output.
1 parent e415721 commit a9ae734

File tree

12 files changed

+246
-236
lines changed

12 files changed

+246
-236
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def send_recv(self, command):
337337
self.send_packet(
338338
{
339339
"type": "response",
340-
"seq": -1,
340+
"seq": 0,
341341
"request_seq": response_or_request["seq"],
342342
"success": True,
343343
"command": "runInTerminal",
@@ -349,7 +349,7 @@ def send_recv(self, command):
349349
self.send_packet(
350350
{
351351
"type": "response",
352-
"seq": -1,
352+
"seq": 0,
353353
"request_seq": response_or_request["seq"],
354354
"success": True,
355355
"command": "startDebugging",

lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test_terminated_event(self):
4343
self.continue_to_breakpoints(breakpoint_ids)
4444
self.continue_to_exit()
4545

46-
statistics = self.dap_server.wait_for_terminated()["statistics"]
46+
statistics = self.dap_server.wait_for_terminated()["body"]["$__lldb_statistics"]
4747
self.assertGreater(statistics["totalDebugInfoByteSize"], 0)
4848
self.assertGreater(statistics["totalDebugInfoEnabled"], 0)
4949
self.assertGreater(statistics["totalModuleCountHasDebugInfo"], 0)

lldb/tools/lldb-dap/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ add_lldb_tool(lldb-dap
2828
FifoFiles.cpp
2929
FunctionBreakpoint.cpp
3030
InstructionBreakpoint.cpp
31-
IOStream.cpp
3231
JSONUtils.cpp
3332
LLDBUtils.cpp
3433
OutputRedirector.cpp
3534
ProgressEvent.cpp
35+
Protocol.cpp
3636
RunInTerminal.cpp
3737
SourceBreakpoint.cpp
38-
Protocol.cpp
38+
Transport.cpp
3939
Watchpoint.cpp
4040

4141
Handler/ResponseHandler.cpp

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 32 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "JSONUtils.h"
1212
#include "LLDBUtils.h"
1313
#include "OutputRedirector.h"
14+
#include "Transport.h"
1415
#include "lldb/API/SBBreakpoint.h"
1516
#include "lldb/API/SBCommandInterpreter.h"
1617
#include "lldb/API/SBCommandReturnObject.h"
@@ -64,8 +65,8 @@ namespace lldb_dap {
6465
DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log,
6566
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
6667
std::vector<std::string> pre_init_commands)
67-
: name(std::move(name)), debug_adapter_path(path), log(log),
68-
input(std::move(input)), output(std::move(output)),
68+
: client_name(std::move(name)), debug_adapter_path(path), log(log),
69+
transport(client_name, std::move(input), std::move(output)),
6970
broadcaster("lldb-dap"), exception_breakpoints(),
7071
pre_init_commands(std::move(pre_init_commands)),
7172
focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false),
@@ -219,65 +220,27 @@ void DAP::StopEventHandlers() {
219220
}
220221
}
221222

222-
// Send the JSON in "json_str" to the "out" stream. Correctly send the
223-
// "Content-Length:" field followed by the length, followed by the raw
224-
// JSON bytes.
225-
void DAP::SendJSON(const std::string &json_str) {
226-
output.write_full("Content-Length: ");
227-
output.write_full(llvm::utostr(json_str.size()));
228-
output.write_full("\r\n\r\n");
229-
output.write_full(json_str);
230-
}
231-
232223
// Serialize the JSON value into a string and send the JSON packet to
233224
// the "out" stream.
234225
void DAP::SendJSON(const llvm::json::Value &json) {
235-
std::string json_str;
236-
llvm::raw_string_ostream strm(json_str);
237-
strm << json;
238-
static std::mutex mutex;
239-
std::lock_guard<std::mutex> locker(mutex);
240-
SendJSON(json_str);
241-
242-
if (log) {
243-
auto now = std::chrono::duration<double>(
244-
std::chrono::system_clock::now().time_since_epoch());
245-
*log << llvm::formatv("{0:f9} {1} <-- ", now.count(), name).str()
246-
<< std::endl
247-
<< "Content-Length: " << json_str.size() << "\r\n\r\n"
248-
<< llvm::formatv("{0:2}", json).str() << std::endl;
249-
}
250-
}
251-
252-
// Read a JSON packet from the "in" stream.
253-
std::string DAP::ReadJSON() {
254-
std::string length_str;
255-
std::string json_str;
256-
int length;
257-
258-
if (!input.read_expected(log, "Content-Length: "))
259-
return json_str;
260-
261-
if (!input.read_line(log, length_str))
262-
return json_str;
263-
264-
if (!llvm::to_integer(length_str, length))
265-
return json_str;
266-
267-
if (!input.read_expected(log, "\r\n"))
268-
return json_str;
269-
270-
if (!input.read_full(log, length, json_str))
271-
return json_str;
272-
273-
if (log) {
274-
auto now = std::chrono::duration<double>(
275-
std::chrono::system_clock::now().time_since_epoch());
276-
*log << llvm::formatv("{0:f9} {1} --> ", now.count(), name).str()
277-
<< std::endl
278-
<< "Content-Length: " << length << "\r\n\r\n";
226+
// FIXME: Instead of parsing the output message from JSON, pass the `Message`
227+
// as parameter to `SendJSON`.
228+
protocol::Message M;
229+
llvm::json::Path::Root root;
230+
if (!protocol::fromJSON(json, M, root)) {
231+
if (log) {
232+
std::string error;
233+
llvm::raw_string_ostream OS(error);
234+
root.printErrorContext(json, OS);
235+
*log << "encoding failure: " << error << "\n";
236+
}
237+
return;
279238
}
280-
return json_str;
239+
auto status = transport.Write(log, M);
240+
if (status.Fail() && log)
241+
*log << llvm::formatv("failed to send {0}: {1}\n", llvm::json::Value(M),
242+
status.AsCString())
243+
.str();
281244
}
282245

283246
// "OutputEvent": {
@@ -704,36 +667,10 @@ void DAP::SetTarget(const lldb::SBTarget target) {
704667
}
705668
}
706669

707-
PacketStatus DAP::GetNextObject(llvm::json::Object &object) {
708-
std::string json = ReadJSON();
709-
if (json.empty())
710-
return PacketStatus::EndOfFile;
711-
712-
llvm::StringRef json_sref(json);
713-
llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
714-
if (auto error = json_value.takeError()) {
715-
std::string error_str = llvm::toString(std::move(error));
716-
if (log)
717-
*log << "error: failed to parse JSON: " << error_str << std::endl
718-
<< json << std::endl;
719-
return PacketStatus::JSONMalformed;
720-
}
721-
722-
if (log) {
723-
*log << llvm::formatv("{0:2}", *json_value).str() << std::endl;
724-
}
725-
726-
llvm::json::Object *object_ptr = json_value->getAsObject();
727-
if (!object_ptr) {
728-
if (log)
729-
*log << "error: json packet isn't a object" << std::endl;
730-
return PacketStatus::JSONNotObject;
731-
}
732-
object = *object_ptr;
733-
return PacketStatus::Success;
734-
}
735-
736-
bool DAP::HandleObject(const llvm::json::Object &object) {
670+
bool DAP::HandleObject(const protocol::Message &M) {
671+
// FIXME: Directly handle `Message` instead of serializing to JSON.
672+
llvm::json::Value v = toJSON(M);
673+
llvm::json::Object object = *v.getAsObject();
737674
const auto packet_type = GetString(object, "type");
738675
if (packet_type == "request") {
739676
const auto command = GetString(object, "command");
@@ -838,19 +775,16 @@ llvm::Error DAP::Loop() {
838775
StopEventHandlers();
839776
});
840777
while (!disconnecting) {
841-
llvm::json::Object object;
842-
lldb_dap::PacketStatus status = GetNextObject(object);
843-
844-
if (status == lldb_dap::PacketStatus::EndOfFile) {
845-
break;
846-
}
847-
848-
if (status != lldb_dap::PacketStatus::Success) {
849-
return llvm::createStringError(llvm::inconvertibleErrorCode(),
850-
"failed to send packet");
778+
auto next = transport.Read(log);
779+
if (auto Err = next.takeError()) {
780+
// On EOF, simply break out of the loop.
781+
std::error_code ec = llvm::errorToErrorCode(std::move(Err));
782+
if (ec == Transport::kEOF)
783+
break;
784+
return llvm::errorCodeToError(ec);
851785
}
852786

853-
if (!HandleObject(object)) {
787+
if (!HandleObject(*next)) {
854788
return llvm::createStringError(llvm::inconvertibleErrorCode(),
855789
"unhandled packet");
856790
}

lldb/tools/lldb-dap/DAP.h

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
#include "FunctionBreakpoint.h"
1515
#include "Handler/RequestHandler.h"
1616
#include "Handler/ResponseHandler.h"
17-
#include "IOStream.h"
1817
#include "InstructionBreakpoint.h"
1918
#include "OutputRedirector.h"
2019
#include "ProgressEvent.h"
20+
#include "Protocol.h"
2121
#include "SourceBreakpoint.h"
22+
#include "Transport.h"
2223
#include "lldb/API/SBBroadcaster.h"
2324
#include "lldb/API/SBCommandInterpreter.h"
2425
#include "lldb/API/SBDebugger.h"
@@ -39,7 +40,6 @@
3940
#include "llvm/Support/Error.h"
4041
#include "llvm/Support/JSON.h"
4142
#include "llvm/Support/Threading.h"
42-
#include <map>
4343
#include <memory>
4444
#include <mutex>
4545
#include <optional>
@@ -145,11 +145,10 @@ struct SendEventRequestHandler : public lldb::SBCommandPluginInterface {
145145
};
146146

147147
struct DAP {
148-
std::string name;
148+
std::string client_name;
149149
llvm::StringRef debug_adapter_path;
150150
std::ofstream *log;
151-
InputStream input;
152-
OutputStream output;
151+
Transport transport;
153152
lldb::SBFile in;
154153
OutputRedirector out;
155154
OutputRedirector err;
@@ -233,8 +232,6 @@ struct DAP {
233232
// the "out" stream.
234233
void SendJSON(const llvm::json::Value &json);
235234

236-
std::string ReadJSON();
237-
238235
void SendOutput(OutputType o, const llvm::StringRef output);
239236

240237
void SendProgressEvent(uint64_t progress_id, const char *message,
@@ -307,8 +304,7 @@ struct DAP {
307304
/// listeing for its breakpoint events.
308305
void SetTarget(const lldb::SBTarget target);
309306

310-
PacketStatus GetNextObject(llvm::json::Object &object);
311-
bool HandleObject(const llvm::json::Object &object);
307+
bool HandleObject(const protocol::Message &M);
312308

313309
/// Disconnect the DAP session.
314310
lldb::SBError Disconnect();
@@ -382,12 +378,6 @@ struct DAP {
382378
InstructionBreakpoint *GetInstructionBreakpoint(const lldb::break_id_t bp_id);
383379

384380
InstructionBreakpoint *GetInstructionBPFromStopReason(lldb::SBThread &thread);
385-
386-
private:
387-
// Send the JSON in "json_str" to the "out" stream. Correctly send the
388-
// "Content-Length:" field followed by the length, followed by the raw
389-
// JSON bytes.
390-
void SendJSON(const std::string &json_str);
391381
};
392382

393383
} // namespace lldb_dap

lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ void ProgressEventThreadFunction(DAP &dap) {
111111
// them prevent multiple threads from writing simultaneously so no locking
112112
// is required.
113113
static void EventThreadFunction(DAP &dap) {
114-
llvm::set_thread_name(dap.name + ".event_handler");
114+
llvm::set_thread_name(dap.client_name + ".event_handler");
115115
lldb::SBEvent event;
116116
lldb::SBListener listener = dap.debugger.GetListener();
117117
dap.broadcaster.AddListener(listener, eBroadcastBitStopEventThread);

lldb/tools/lldb-dap/IOStream.cpp

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)