Skip to content

Commit c340c38

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 f159836 commit c340c38

File tree

8 files changed

+240
-211
lines changed

8 files changed

+240
-211
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/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 & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "JSONUtils.h"
1313
#include "LLDBUtils.h"
1414
#include "OutputRedirector.h"
15+
#include "Transport.h"
1516
#include "lldb/API/SBBreakpoint.h"
1617
#include "lldb/API/SBCommandInterpreter.h"
1718
#include "lldb/API/SBCommandReturnObject.h"
@@ -67,7 +68,7 @@ DAP::DAP(llvm::StringRef client_name, llvm::StringRef path, std::ofstream *log,
6768
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
6869
std::vector<std::string> pre_init_commands)
6970
: client_name(client_name), debug_adapter_path(path), log(log),
70-
input(std::move(input)), output(std::move(output)),
71+
transport(client_name, std::move(input), std::move(output)),
7172
broadcaster("lldb-dap"), exception_breakpoints(),
7273
pre_init_commands(std::move(pre_init_commands)),
7374
focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false),
@@ -221,52 +222,27 @@ void DAP::StopEventHandlers() {
221222
}
222223
}
223224

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

272248
// "OutputEvent": {
@@ -693,29 +669,10 @@ void DAP::SetTarget(const lldb::SBTarget target) {
693669
}
694670
}
695671

696-
PacketStatus DAP::GetNextObject(llvm::json::Object &object) {
697-
std::string json = ReadJSON();
698-
if (json.empty())
699-
return PacketStatus::EndOfFile;
700-
701-
llvm::StringRef json_sref(json);
702-
llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
703-
if (!json_value) {
704-
DAP_LOG_ERROR(log, json_value.takeError(),
705-
"({1}) failed to parse JSON: {0}", client_name);
706-
return PacketStatus::JSONMalformed;
707-
}
708-
709-
llvm::json::Object *object_ptr = json_value->getAsObject();
710-
if (!object_ptr) {
711-
DAP_LOG(log, "({0}) error: json packet isn't a object", client_name);
712-
return PacketStatus::JSONNotObject;
713-
}
714-
object = *object_ptr;
715-
return PacketStatus::Success;
716-
}
717-
718-
bool DAP::HandleObject(const llvm::json::Object &object) {
672+
bool DAP::HandleObject(const protocol::Message &M) {
673+
// FIXME: Directly handle `Message` instead of serializing to JSON.
674+
llvm::json::Value v = toJSON(M);
675+
llvm::json::Object object = *v.getAsObject();
719676
const auto packet_type = GetString(object, "type");
720677
if (packet_type == "request") {
721678
const auto command = GetString(object, "command");
@@ -818,19 +775,16 @@ llvm::Error DAP::Loop() {
818775
StopEventHandlers();
819776
});
820777
while (!disconnecting) {
821-
llvm::json::Object object;
822-
lldb_dap::PacketStatus status = GetNextObject(object);
823-
824-
if (status == lldb_dap::PacketStatus::EndOfFile) {
825-
break;
826-
}
827-
828-
if (status != lldb_dap::PacketStatus::Success) {
829-
return llvm::createStringError(llvm::inconvertibleErrorCode(),
830-
"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);
831785
}
832786

833-
if (!HandleObject(object)) {
787+
if (!HandleObject(*next)) {
834788
return llvm::createStringError(llvm::inconvertibleErrorCode(),
835789
"unhandled packet");
836790
}

lldb/tools/lldb-dap/DAP.h

Lines changed: 4 additions & 14 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>
@@ -148,8 +148,7 @@ struct DAP {
148148
llvm::StringRef 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/IOStream.cpp

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

lldb/tools/lldb-dap/IOStream.h

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

0 commit comments

Comments
 (0)