|
11 | 11 | #include "JSONUtils.h"
|
12 | 12 | #include "LLDBUtils.h"
|
13 | 13 | #include "OutputRedirector.h"
|
| 14 | +#include "Transport.h" |
14 | 15 | #include "lldb/API/SBBreakpoint.h"
|
15 | 16 | #include "lldb/API/SBCommandInterpreter.h"
|
16 | 17 | #include "lldb/API/SBCommandReturnObject.h"
|
@@ -65,7 +66,7 @@ DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log,
|
65 | 66 | lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
|
66 | 67 | std::vector<std::string> pre_init_commands)
|
67 | 68 | : 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)), |
69 | 70 | broadcaster("lldb-dap"), exception_breakpoints(),
|
70 | 71 | pre_init_commands(std::move(pre_init_commands)),
|
71 | 72 | focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false),
|
@@ -237,65 +238,25 @@ void DAP::StopEventHandlers() {
|
237 | 238 | }
|
238 | 239 | }
|
239 | 240 |
|
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 |
| - |
250 | 241 | // Serialize the JSON value into a string and send the JSON packet to
|
251 | 242 | // the "out" stream.
|
252 | 243 | 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; |
297 | 254 | }
|
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(); |
299 | 260 | }
|
300 | 261 |
|
301 | 262 | // "OutputEvent": {
|
@@ -722,40 +683,9 @@ void DAP::SetTarget(const lldb::SBTarget target) {
|
722 | 683 | }
|
723 | 684 | }
|
724 | 685 |
|
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(); |
759 | 689 | const auto packet_type = GetString(object, "type");
|
760 | 690 | if (packet_type == "request") {
|
761 | 691 | const auto command = GetString(object, "command");
|
@@ -858,25 +788,18 @@ lldb::SBError DAP::Disconnect(bool terminateDebuggee) {
|
858 | 788 | }
|
859 | 789 |
|
860 | 790 | 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(); }); |
866 | 792 | 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(); |
877 | 800 | }
|
878 | 801 |
|
879 |
| - if (!HandleObject(object)) { |
| 802 | + if (!HandleObject(next)) { |
880 | 803 | return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
881 | 804 | "unhandled packet");
|
882 | 805 | }
|
|
0 commit comments