Skip to content

Commit 2283694

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 45759fe commit 2283694

File tree

10 files changed

+248
-241
lines changed

10 files changed

+248
-241
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: 29 additions & 106 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"
@@ -65,7 +66,7 @@ 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)
6768
: name(std::move(name)), debug_adapter_path(path), log(log),
68-
input(std::move(input)), output(std::move(output)),
69+
transport(this->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),
@@ -237,65 +238,25 @@ void DAP::StopEventHandlers() {
237238
}
238239
}
239240

240-
// Send the JSON in "json_str" to the "out" stream. Correctly send the
241-
// "Content-Length:" field followed by the length, followed by the raw
242-
// JSON bytes.
243-
void DAP::SendJSON(const std::string &json_str) {
244-
output.write_full("Content-Length: ");
245-
output.write_full(llvm::utostr(json_str.size()));
246-
output.write_full("\r\n\r\n");
247-
output.write_full(json_str);
248-
}
249-
250241
// Serialize the JSON value into a string and send the JSON packet to
251242
// the "out" stream.
252243
void DAP::SendJSON(const llvm::json::Value &json) {
253-
std::string json_str;
254-
llvm::raw_string_ostream strm(json_str);
255-
strm << json;
256-
static std::mutex mutex;
257-
std::lock_guard<std::mutex> locker(mutex);
258-
SendJSON(json_str);
259-
260-
if (log) {
261-
auto now = std::chrono::duration<double>(
262-
std::chrono::system_clock::now().time_since_epoch());
263-
*log << llvm::formatv("{0:f9} {1} <-- ", now.count(), name).str()
264-
<< std::endl
265-
<< "Content-Length: " << json_str.size() << "\r\n\r\n"
266-
<< llvm::formatv("{0:2}", json).str() << std::endl;
267-
}
268-
}
269-
270-
// Read a JSON packet from the "in" stream.
271-
std::string DAP::ReadJSON() {
272-
std::string length_str;
273-
std::string json_str;
274-
int length;
275-
276-
if (!input.read_expected(log, "Content-Length: "))
277-
return json_str;
278-
279-
if (!input.read_line(log, length_str))
280-
return json_str;
281-
282-
if (!llvm::to_integer(length_str, length))
283-
return json_str;
284-
285-
if (!input.read_expected(log, "\r\n"))
286-
return json_str;
287-
288-
if (!input.read_full(log, length, json_str))
289-
return json_str;
290-
291-
if (log) {
292-
auto now = std::chrono::duration<double>(
293-
std::chrono::system_clock::now().time_since_epoch());
294-
*log << llvm::formatv("{0:f9} {1} --> ", now.count(), name).str()
295-
<< std::endl
296-
<< "Content-Length: " << length << "\r\n\r\n";
244+
protocol::Message M;
245+
llvm::json::Path::Root root;
246+
if (!protocol::fromJSON(json, M, root)) {
247+
if (log) {
248+
std::string error;
249+
llvm::raw_string_ostream OS(error);
250+
root.printErrorContext(json, OS);
251+
*log << "encoding failure: " << error << "\n";
252+
}
253+
return;
297254
}
298-
return json_str;
255+
auto status = transport.Write(log, M);
256+
if (status.Fail() && log)
257+
*log << llvm::formatv("failed to send {0}: {1}\n", llvm::json::Value(M),
258+
status.AsCString())
259+
.str();
299260
}
300261

301262
// "OutputEvent": {
@@ -722,40 +683,9 @@ void DAP::SetTarget(const lldb::SBTarget target) {
722683
}
723684
}
724685

725-
PacketStatus DAP::GetNextObject(llvm::json::Object &object) {
726-
std::string json = ReadJSON();
727-
if (json.empty())
728-
return PacketStatus::EndOfFile;
729-
730-
llvm::StringRef json_sref(json);
731-
llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
732-
if (!json_value) {
733-
auto error = json_value.takeError();
734-
if (log) {
735-
std::string error_str;
736-
llvm::raw_string_ostream strm(error_str);
737-
strm << error;
738-
*log << "error: failed to parse JSON: " << error_str << std::endl
739-
<< json << std::endl;
740-
}
741-
return PacketStatus::JSONMalformed;
742-
}
743-
744-
if (log) {
745-
*log << llvm::formatv("{0:2}", *json_value).str() << std::endl;
746-
}
747-
748-
llvm::json::Object *object_ptr = json_value->getAsObject();
749-
if (!object_ptr) {
750-
if (log)
751-
*log << "error: json packet isn't a object" << std::endl;
752-
return PacketStatus::JSONNotObject;
753-
}
754-
object = *object_ptr;
755-
return PacketStatus::Success;
756-
}
757-
758-
bool DAP::HandleObject(const llvm::json::Object &object) {
686+
bool DAP::HandleObject(const protocol::Message &M) {
687+
llvm::json::Value v = toJSON(M);
688+
llvm::json::Object object = *v.getAsObject();
759689
const auto packet_type = GetString(object, "type");
760690
if (packet_type == "request") {
761691
const auto command = GetString(object, "command");
@@ -858,25 +788,18 @@ lldb::SBError DAP::Disconnect(bool terminateDebuggee) {
858788
}
859789

860790
llvm::Error DAP::Loop() {
861-
auto cleanup = llvm::make_scope_exit([this]() {
862-
if (output.descriptor)
863-
output.descriptor->Close();
864-
StopEventHandlers();
865-
});
791+
auto cleanup = llvm::make_scope_exit([this]() { StopEventHandlers(); });
866792
while (!disconnecting) {
867-
llvm::json::Object object;
868-
lldb_dap::PacketStatus status = GetNextObject(object);
869-
870-
if (status == lldb_dap::PacketStatus::EndOfFile) {
871-
break;
872-
}
873-
874-
if (status != lldb_dap::PacketStatus::Success) {
875-
return llvm::createStringError(llvm::inconvertibleErrorCode(),
876-
"failed to send packet");
793+
protocol::Message next;
794+
auto status = transport.Read(log, next);
795+
if (status.Fail()) {
796+
// On EOF, simply break out of the loop.
797+
if (status.GetError() == Transport::kEOF)
798+
break;
799+
return status.takeError();
877800
}
878801

879-
if (!HandleObject(object)) {
802+
if (!HandleObject(next)) {
880803
return llvm::createStringError(llvm::inconvertibleErrorCode(),
881804
"unhandled packet");
882805
}

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
std::string 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.

0 commit comments

Comments
 (0)