77// ===----------------------------------------------------------------------===//
88
99#include " DAP.h"
10+ #include " DAPLog.h"
1011#include " Handler/ResponseHandler.h"
1112#include " JSONUtils.h"
1213#include " LLDBUtils.h"
1314#include " OutputRedirector.h"
15+ #include " Protocol.h"
1416#include " lldb/API/SBBreakpoint.h"
1517#include " lldb/API/SBCommandInterpreter.h"
1618#include " lldb/API/SBCommandReturnObject.h"
2931#include " llvm/Support/Error.h"
3032#include " llvm/Support/ErrorHandling.h"
3133#include " llvm/Support/FormatVariadic.h"
34+ #include " llvm/Support/JSON.h"
3235#include " llvm/Support/raw_ostream.h"
3336#include < algorithm>
3437#include < cassert>
5053#endif
5154
5255using namespace lldb_dap ;
56+ using namespace lldb_private ;
5357
5458namespace {
5559#ifdef _WIN32
@@ -61,11 +65,11 @@ const char DEV_NULL[] = "/dev/null";
6165
6266namespace lldb_dap {
6367
64- DAP::DAP (std::string name, llvm::StringRef path, std::ofstream *log,
68+ DAP::DAP (llvm::StringRef name, llvm::StringRef path, std::ofstream *log,
6569 lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
6670 std::vector<std::string> pre_init_commands)
67- : name(std::move( name) ), debug_adaptor_path(path), log(log),
68- input ( std::move(input)), output( std::move(output)),
71+ : name(name), debug_adaptor_path(path), log(log),
72+ transport (name, std::move(input), std::move(output)),
6973 broadcaster(" lldb-dap" ), exception_breakpoints(),
7074 pre_init_commands(std::move(pre_init_commands)),
7175 focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false ), is_attach(false ),
@@ -237,65 +241,22 @@ void DAP::StopEventHandlers() {
237241 }
238242}
239243
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-
250244// Serialize the JSON value into a string and send the JSON packet to
251245// the "out" stream.
252246void 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 " ;
247+ protocol::ProtocolMessage M;
248+ llvm::json::Path::Root root;
249+ if (!protocol::fromJSON (json, M, root)) {
250+ if (log) {
251+ std::string error;
252+ llvm::raw_string_ostream OS (error);
253+ root.printErrorContext (json, OS);
254+ *log << " encoding failure: " << error << " \n " ;
255+ }
297256 }
298- return json_str;
257+ auto status = transport.Write (M);
258+ if (status.Fail () && log)
259+ *log << " transport failure: " << status.AsCString () << " \n " ;
299260}
300261
301262// "OutputEvent": {
@@ -720,40 +681,13 @@ void DAP::SetTarget(const lldb::SBTarget target) {
720681 }
721682}
722683
723- PacketStatus DAP::GetNextObject (llvm::json::Object &object) {
724- std::string json = ReadJSON ();
725- if (json.empty ())
726- return PacketStatus::EndOfFile;
727-
728- llvm::StringRef json_sref (json);
729- llvm::Expected<llvm::json::Value> json_value = llvm::json::parse (json_sref);
730- if (!json_value) {
731- auto error = json_value.takeError ();
732- if (log) {
733- std::string error_str;
734- llvm::raw_string_ostream strm (error_str);
735- strm << error;
736- *log << " error: failed to parse JSON: " << error_str << std::endl
737- << json << std::endl;
738- }
739- return PacketStatus::JSONMalformed;
740- }
741-
742- if (log) {
743- *log << llvm::formatv (" {0:2}" , *json_value).str () << std::endl;
744- }
745-
746- llvm::json::Object *object_ptr = json_value->getAsObject ();
747- if (!object_ptr) {
748- if (log)
749- *log << " error: json packet isn't a object" << std::endl;
750- return PacketStatus::JSONNotObject;
751- }
752- object = *object_ptr;
753- return PacketStatus::Success;
684+ llvm::Expected<protocol::ProtocolMessage> DAP::GetNextObject () {
685+ return transport.Read ();
754686}
755687
756- bool DAP::HandleObject (const llvm::json::Object &object) {
688+ bool DAP::HandleObject (const protocol::ProtocolMessage &M) {
689+ llvm::json::Value v = toJSON (M);
690+ llvm::json::Object object = *v.getAsObject ();
757691 const auto packet_type = GetString (object, " type" );
758692 if (packet_type == " request" ) {
759693 const auto command = GetString (object, " command" );
@@ -764,9 +698,8 @@ bool DAP::HandleObject(const llvm::json::Object &object) {
764698 return true ; // Success
765699 }
766700
767- if (log)
768- *log << " error: unhandled command \" " << command.data () << " \" "
769- << std::endl;
701+ LLDB_LOG (GetLog (DAPLog::Protocol), " Unhandled command {0}" , command);
702+
770703 return false ; // Fail
771704 }
772705
@@ -805,6 +738,8 @@ bool DAP::HandleObject(const llvm::json::Object &object) {
805738 return true ;
806739 }
807740
741+ LLDB_LOG (GetLog (DAPLog::Protocol), " Unsupported protocol message" );
742+
808743 return false ;
809744}
810745
@@ -858,19 +793,13 @@ lldb::SBError DAP::Disconnect(bool terminateDebuggee) {
858793llvm::Error DAP::Loop () {
859794 auto cleanup = llvm::make_scope_exit ([this ]() { StopEventHandlers (); });
860795 while (!disconnecting) {
861- llvm::json::Object object;
862- lldb_dap::PacketStatus status = GetNextObject (object);
863-
864- if (status == lldb_dap::PacketStatus::EndOfFile) {
865- break ;
866- }
796+ auto next = GetNextObject ();
867797
868- if (status != lldb_dap::PacketStatus::Success) {
869- return llvm::createStringError (llvm::inconvertibleErrorCode (),
870- " failed to send packet" );
798+ if (!next) {
799+ return next.takeError ();
871800 }
872801
873- if (!HandleObject (object )) {
802+ if (!HandleObject (*next )) {
874803 return llvm::createStringError (llvm::inconvertibleErrorCode (),
875804 " unhandled packet" );
876805 }
0 commit comments