77// ===----------------------------------------------------------------------===//
88
99#include " Transport.h"
10+ #include " DAPLog.h"
1011#include " Protocol.h"
11- #include " c++/v1/__system_error/error_code.h"
1212#include " lldb/Utility/IOObject.h"
1313#include " lldb/Utility/Status.h"
1414#include " lldb/lldb-forward.h"
1515#include " llvm/ADT/StringExtras.h"
16+ #include " llvm/ADT/StringRef.h"
1617#include " llvm/Support/Error.h"
1718#include " llvm/Support/raw_ostream.h"
1819#include < string>
19- #include < system_error>
2020#include < utility>
2121
2222using namespace llvm ;
@@ -28,18 +28,11 @@ using namespace lldb_dap::protocol;
2828static Expected<std::string> ReadFull (IOObjectSP &descriptor, size_t length) {
2929 if (!descriptor || !descriptor->IsValid ())
3030 return createStringError (" transport input is closed" );
31-
3231 std::string data;
3332 data.resize (length);
34-
3533 auto status = descriptor->Read (data.data (), length);
3634 if (status.Fail ())
3735 return status.takeError ();
38-
39- // If we got back zero then we have reached EOF.
40- if (length == 0 )
41- return createStringError (Transport::kEOF , " end-of-file" );
42-
4336 return data.substr (0 , length);
4437}
4538
@@ -48,99 +41,101 @@ static Expected<std::string> ReadUntil(IOObjectSP &descriptor,
4841 std::string buffer;
4942 buffer.reserve (delimiter.size () + 1 );
5043 while (!llvm::StringRef (buffer).ends_with (delimiter)) {
51- auto next = ReadFull (descriptor, 1 );
44+ Expected<std::string> next =
45+ ReadFull (descriptor, buffer.empty () ? delimiter.size () : 1 );
5246 if (auto Err = next.takeError ())
5347 return std::move (Err);
48+ // '' is returned on EOF.
49+ if (next->empty ())
50+ return buffer;
5451 buffer += *next;
5552 }
5653 return buffer.substr (0 , buffer.size () - delimiter.size ());
5754}
5855
59- static Error ReadExpected (IOObjectSP &descriptor, StringRef want) {
60- auto got = ReadFull (descriptor, want.size ());
61- if (auto Err = got.takeError ())
62- return Err;
63- if (*got != want) {
64- return createStringError (" want %s, got %s" , want.str ().c_str (),
65- got->c_str ());
66- }
67- return Error::success ();
68- }
56+ // / DAP message format
57+ // / ```
58+ // / Content-Length: (?<length>\d+)\r\n\r\n(?<content>.{\k<length>})
59+ // / ```
60+ static const StringLiteral kHeaderContentLength = " Content-Length: " ;
61+ static const StringLiteral kHeaderSeparator = " \r\n\r\n " ;
6962
7063namespace lldb_dap {
7164
72- const std::error_code Transport::kEOF =
73- std::error_code (0x1001 , std::generic_category());
74-
75- Transport::Transport (StringRef client_name, IOObjectSP input, IOObjectSP output)
76- : m_client_name(client_name), m_input(std::move(input)),
65+ Transport::Transport (StringRef client_name, std::ofstream *log,
66+ IOObjectSP input, IOObjectSP output)
67+ : m_client_name(client_name), m_log(log), m_input(std::move(input)),
7768 m_output (std::move(output)) {}
7869
79- Expected<protocol::Message> Transport::Read (std::ofstream *log) {
80- // If we don't find the expected header we have reached EOF.
81- if (auto Err = ReadExpected (m_input, " Content-Length: " ))
82- return std::move (Err);
70+ std::optional<Message> Transport::Read () {
71+ Expected<std::string> message_header =
72+ ReadFull (m_input, kHeaderContentLength .size ());
73+ if (!message_header) {
74+ DAP_LOG_ERROR (m_log, message_header.takeError (), " ({1}) read failed: {0}" ,
75+ m_client_name);
76+ return std::nullopt ;
77+ }
8378
84- auto rawLength = ReadUntil (m_input, " \r\n\r\n " );
85- if (auto Err = rawLength.takeError ())
86- return std::move (Err);
79+ // '' returned on EOF.
80+ if (message_header->empty ())
81+ return std::nullopt ;
82+ if (*message_header != kHeaderContentLength ) {
83+ DAP_LOG (m_log, " ({0}) read failed: expected '{1}' and got '{2}'" ,
84+ m_client_name, kHeaderContentLength , *message_header);
85+ return std::nullopt ;
86+ }
87+
88+ Expected<std::string> raw_length = ReadUntil (m_input, kHeaderSeparator );
89+ if (!raw_length) {
90+ DAP_LOG_ERROR (m_log, raw_length.takeError (), " ({1}) read failed: {0}" ,
91+ m_client_name);
92+ return std::nullopt ;
93+ }
8794
8895 size_t length;
89- if (!to_integer (*rawLength, length))
90- return createStringError (" invalid content length %s" , rawLength->c_str ());
91-
92- auto rawJSON = ReadFull (m_input, length);
93- if (auto Err = rawJSON.takeError ())
94- return std::move (Err);
95- if (rawJSON->length () != length)
96- return createStringError (
97- " malformed request, expected %ld bytes, got %ld bytes" , length,
98- rawJSON->length ());
99-
100- if (log) {
101- auto now = std::chrono::duration<double >(
102- std::chrono::system_clock::now ().time_since_epoch ());
103- *log << formatv (" {0:f9} <-- ({1}) {2}\n " , now.count (), m_client_name,
104- *rawJSON)
105- .str ();
96+ if (!to_integer (*raw_length, length)) {
97+ DAP_LOG (m_log, " ({0}) read failed: invalid content length {1}" ,
98+ m_client_name, *raw_length);
99+ return std::nullopt ;
106100 }
107101
108- auto JSON = json::parse (*rawJSON);
109- if (auto Err = JSON.takeError ()) {
110- return createStringError (" malformed JSON %s\n %s" , rawJSON->c_str (),
111- llvm::toString (std::move (Err)).c_str ());
102+ Expected<std::string> raw_json = ReadFull (m_input, length);
103+ if (!raw_json) {
104+ DAP_LOG_ERROR (m_log, raw_json.takeError (), " ({1}) read failed: {0}" ,
105+ m_client_name);
106+ return std::nullopt ;
107+ }
108+ if (raw_json->length () != length) {
109+ DAP_LOG (m_log, " ({0}) read failed: expected {1} bytes and got {2} bytes" ,
110+ m_client_name, length, raw_json->length ());
111+ return std::nullopt ;
112112 }
113113
114- protocol::Message M ;
115- llvm::json::Path::Root Root;
116- if (! fromJSON (*JSON, M, Root)) {
117- std::string error;
118- raw_string_ostream OS (error);
119- Root. printErrorContext (*JSON, OS );
120- return createStringError ( " malformed request: %s " , error. c_str ()) ;
114+ DAP_LOG (m_log, " <-- ({0}) {1} " , m_client_name, *raw_json) ;
115+
116+ llvm::Expected<Message> message = json::parse<Message>(*raw_json);
117+ if (!message) {
118+ DAP_LOG_ERROR (m_log, message. takeError (), " ({1}) read failed: {0} " ,
119+ m_client_name );
120+ return std:: nullopt ;
121121 }
122- return std::move (M);
122+
123+ return std::move (*message);
123124}
124125
125- lldb_private::Status Transport::Write (std::ofstream *log,
126- const protocol::Message &M) {
126+ Error Transport::Write (const Message &message) {
127127 if (!m_output || !m_output->IsValid ())
128- return Status (" transport output is closed" );
128+ return createStringError (" transport output is closed" );
129129
130- std::string JSON = formatv (" {0}" , toJSON (M )).str ();
130+ std::string json = formatv (" {0}" , toJSON (message )).str ();
131131
132- if (log) {
133- auto now = std::chrono::duration<double >(
134- std::chrono::system_clock::now ().time_since_epoch ());
135- *log << formatv (" {0:f9} --> ({1}) {2}\n " , now.count (), m_client_name, JSON)
136- .str ();
137- }
132+ DAP_LOG (m_log, " --> ({0}) {1}" , m_client_name, json);
138133
139134 std::string Output;
140135 raw_string_ostream OS (Output);
141- OS << " Content-Length: " << JSON .length () << " \r\n\r\n " << JSON ;
136+ OS << kHeaderContentLength << json .length () << kHeaderSeparator << json ;
142137 size_t num_bytes = Output.size ();
143- return m_output->Write (Output.data (), num_bytes);
138+ return m_output->Write (Output.data (), num_bytes). takeError () ;
144139}
145140
146141} // end namespace lldb_dap
0 commit comments