7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " Transport.h"
10
+ #include " DAPLog.h"
10
11
#include " Protocol.h"
11
- #include " c++/v1/__system_error/error_code.h"
12
12
#include " lldb/Utility/IOObject.h"
13
13
#include " lldb/Utility/Status.h"
14
14
#include " lldb/lldb-forward.h"
15
15
#include " llvm/ADT/StringExtras.h"
16
+ #include " llvm/ADT/StringRef.h"
16
17
#include " llvm/Support/Error.h"
17
18
#include " llvm/Support/raw_ostream.h"
18
19
#include < string>
19
- #include < system_error>
20
20
#include < utility>
21
21
22
22
using namespace llvm ;
@@ -28,18 +28,11 @@ using namespace lldb_dap::protocol;
28
28
static Expected<std::string> ReadFull (IOObjectSP &descriptor, size_t length) {
29
29
if (!descriptor || !descriptor->IsValid ())
30
30
return createStringError (" transport input is closed" );
31
-
32
31
std::string data;
33
32
data.resize (length);
34
-
35
33
auto status = descriptor->Read (data.data (), length);
36
34
if (status.Fail ())
37
35
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
-
43
36
return data.substr (0 , length);
44
37
}
45
38
@@ -48,99 +41,101 @@ static Expected<std::string> ReadUntil(IOObjectSP &descriptor,
48
41
std::string buffer;
49
42
buffer.reserve (delimiter.size () + 1 );
50
43
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 );
52
46
if (auto Err = next.takeError ())
53
47
return std::move (Err);
48
+ // '' is returned on EOF.
49
+ if (next->empty ())
50
+ return buffer;
54
51
buffer += *next;
55
52
}
56
53
return buffer.substr (0 , buffer.size () - delimiter.size ());
57
54
}
58
55
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 " ;
69
62
70
63
namespace lldb_dap {
71
64
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)),
77
68
m_output (std::move(output)) {}
78
69
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
+ }
83
78
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
+ }
87
94
88
95
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;
106
100
}
107
101
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;
112
112
}
113
113
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 ;
121
121
}
122
- return std::move (M);
122
+
123
+ return std::move (*message);
123
124
}
124
125
125
- lldb_private::Status Transport::Write (std::ofstream *log,
126
- const protocol::Message &M) {
126
+ Error Transport::Write (const Message &message) {
127
127
if (!m_output || !m_output->IsValid ())
128
- return Status (" transport output is closed" );
128
+ return createStringError (" transport output is closed" );
129
129
130
- std::string JSON = formatv (" {0}" , toJSON (M )).str ();
130
+ std::string json = formatv (" {0}" , toJSON (message )).str ();
131
131
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);
138
133
139
134
std::string Output;
140
135
raw_string_ostream OS (Output);
141
- OS << " Content-Length: " << JSON .length () << " \r\n\r\n " << JSON ;
136
+ OS << kHeaderContentLength << json .length () << kHeaderSeparator << json ;
142
137
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 () ;
144
139
}
145
140
146
141
} // end namespace lldb_dap
0 commit comments