13
13
#ifndef LLDB_HOST_JSONTRANSPORT_H
14
14
#define LLDB_HOST_JSONTRANSPORT_H
15
15
16
- #include " lldb/Host/MainLoopBase.h"
17
16
#include " lldb/lldb-forward.h"
18
- #include " llvm/ADT/FunctionExtras.h"
19
17
#include " llvm/ADT/StringRef.h"
20
18
#include " llvm/Support/Error.h"
21
19
#include " llvm/Support/FormatVariadic.h"
22
20
#include " llvm/Support/JSON.h"
23
- #include < string >
21
+ #include < chrono >
24
22
#include < system_error>
25
- #include < vector>
26
23
27
24
namespace lldb_private {
28
25
@@ -31,33 +28,27 @@ class TransportEOFError : public llvm::ErrorInfo<TransportEOFError> {
31
28
static char ID;
32
29
33
30
TransportEOFError () = default ;
34
- void log (llvm::raw_ostream &OS) const override { OS << " transport EOF" ; }
31
+
32
+ void log (llvm::raw_ostream &OS) const override {
33
+ OS << " transport end of file reached" ;
34
+ }
35
35
std::error_code convertToErrorCode () const override {
36
- return std::make_error_code (std::errc::io_error );
36
+ return llvm::inconvertibleErrorCode ( );
37
37
}
38
38
};
39
39
40
- class TransportUnhandledContentsError
41
- : public llvm::ErrorInfo<TransportUnhandledContentsError> {
40
+ class TransportTimeoutError : public llvm ::ErrorInfo<TransportTimeoutError> {
42
41
public:
43
42
static char ID;
44
43
45
- explicit TransportUnhandledContentsError (std::string unhandled_contents)
46
- : m_unhandled_contents(unhandled_contents) {}
44
+ TransportTimeoutError () = default ;
47
45
48
46
void log (llvm::raw_ostream &OS) const override {
49
- OS << " transport EOF with unhandled contents " << m_unhandled_contents ;
47
+ OS << " transport operation timed out " ;
50
48
}
51
49
std::error_code convertToErrorCode () const override {
52
- return std::make_error_code (std::errc::bad_message );
50
+ return std::make_error_code (std::errc::timed_out );
53
51
}
54
-
55
- const std::string &getUnhandledContents () const {
56
- return m_unhandled_contents;
57
- }
58
-
59
- private:
60
- std::string m_unhandled_contents;
61
52
};
62
53
63
54
class TransportInvalidError : public llvm ::ErrorInfo<TransportInvalidError> {
@@ -77,11 +68,6 @@ class TransportInvalidError : public llvm::ErrorInfo<TransportInvalidError> {
77
68
// / A transport class that uses JSON for communication.
78
69
class JSONTransport {
79
70
public:
80
- using ReadHandleUP = MainLoopBase::ReadHandleUP;
81
- template <typename T>
82
- using Callback =
83
- llvm::unique_function<void (MainLoopBase &, const llvm::Expected<T>)>;
84
-
85
71
JSONTransport (lldb::IOObjectSP input, lldb::IOObjectSP output);
86
72
virtual ~JSONTransport () = default ;
87
73
@@ -97,69 +83,24 @@ class JSONTransport {
97
83
return WriteImpl (message);
98
84
}
99
85
100
- // / Registers the transport with the MainLoop .
86
+ // / Reads the next message from the input stream .
101
87
template <typename T>
102
- llvm::Expected<ReadHandleUP> RegisterReadObject (MainLoopBase &loop,
103
- Callback<T> callback) {
104
- Status error;
105
- ReadHandleUP handle = loop.RegisterReadObject (
106
- m_input,
107
- [&](MainLoopBase &loop) {
108
- char buffer[kReadBufferSize ];
109
- size_t len = sizeof (buffer);
110
- if (llvm::Error error = m_input->Read (buffer, len).takeError ()) {
111
- callback (loop, std::move (error));
112
- return ;
113
- }
114
-
115
- if (len)
116
- m_buffer.append (std::string (buffer, len));
117
-
118
- // If the buffer has contents, try parsing any pending messages.
119
- if (!m_buffer.empty ()) {
120
- llvm::Expected<std::vector<std::string>> messages = Parse ();
121
- if (llvm::Error error = messages.takeError ()) {
122
- callback (loop, std::move (error));
123
- return ;
124
- }
125
-
126
- for (const auto &message : *messages)
127
- if constexpr (std::is_same<T, std::string>::value)
128
- callback (loop, message);
129
- else
130
- callback (loop, llvm::json::parse<T>(message));
131
- }
132
-
133
- // On EOF, notify the callback after the remaining messages were
134
- // handled.
135
- if (len == 0 ) {
136
- if (m_buffer.empty ())
137
- callback (loop, llvm::make_error<TransportEOFError>());
138
- else
139
- callback (loop, llvm::make_error<TransportUnhandledContentsError>(
140
- m_buffer));
141
- }
142
- },
143
- error);
144
- if (error.Fail ())
145
- return error.takeError ();
146
- return handle;
88
+ llvm::Expected<T> Read (const std::chrono::microseconds &timeout) {
89
+ llvm::Expected<std::string> message = ReadImpl (timeout);
90
+ if (!message)
91
+ return message.takeError ();
92
+ return llvm::json::parse<T>(/* JSON=*/ *message);
147
93
}
148
94
149
95
protected:
150
- template <typename ... Ts> inline auto Logv (const char *Fmt, Ts &&...Vals) {
151
- Log (llvm::formatv (Fmt, std::forward<Ts>(Vals)...).str ());
152
- }
153
96
virtual void Log (llvm::StringRef message);
154
97
155
98
virtual llvm::Error WriteImpl (const std::string &message) = 0;
156
- virtual llvm::Expected<std::vector<std::string>> Parse () = 0;
99
+ virtual llvm::Expected<std::string>
100
+ ReadImpl (const std::chrono::microseconds &timeout) = 0 ;
157
101
158
102
lldb::IOObjectSP m_input;
159
103
lldb::IOObjectSP m_output;
160
- std::string m_buffer;
161
-
162
- static constexpr size_t kReadBufferSize = 1024 ;
163
104
};
164
105
165
106
// / A transport class for JSON with a HTTP header.
@@ -170,13 +111,14 @@ class HTTPDelimitedJSONTransport : public JSONTransport {
170
111
virtual ~HTTPDelimitedJSONTransport () = default ;
171
112
172
113
protected:
173
- llvm::Error WriteImpl (const std::string &message) override ;
174
- llvm::Expected<std::vector<std::string>> Parse () override ;
175
-
176
- static constexpr llvm::StringLiteral kHeaderContentLength = " Content-Length" ;
177
- static constexpr llvm::StringLiteral kHeaderFieldSeparator = " :" ;
178
- static constexpr llvm::StringLiteral kHeaderSeparator = " \r\n " ;
179
- static constexpr llvm::StringLiteral kEndOfHeader = " \r\n\r\n " ;
114
+ virtual llvm::Error WriteImpl (const std::string &message) override ;
115
+ virtual llvm::Expected<std::string>
116
+ ReadImpl (const std::chrono::microseconds &timeout) override ;
117
+
118
+ // FIXME: Support any header.
119
+ static constexpr llvm::StringLiteral kHeaderContentLength =
120
+ " Content-Length: " ;
121
+ static constexpr llvm::StringLiteral kHeaderSeparator = " \r\n\r\n " ;
180
122
};
181
123
182
124
// / A transport class for JSON RPC.
@@ -187,8 +129,9 @@ class JSONRPCTransport : public JSONTransport {
187
129
virtual ~JSONRPCTransport () = default ;
188
130
189
131
protected:
190
- llvm::Error WriteImpl (const std::string &message) override ;
191
- llvm::Expected<std::vector<std::string>> Parse () override ;
132
+ virtual llvm::Error WriteImpl (const std::string &message) override ;
133
+ virtual llvm::Expected<std::string>
134
+ ReadImpl (const std::chrono::microseconds &timeout) override ;
192
135
193
136
static constexpr llvm::StringLiteral kMessageSeparator = " \n " ;
194
137
};
0 commit comments