1313#ifndef LLDB_HOST_JSONTRANSPORT_H
1414#define LLDB_HOST_JSONTRANSPORT_H
1515
16- #include " lldb/Host/MainLoopBase.h"
1716#include " lldb/lldb-forward.h"
18- #include " llvm/ADT/FunctionExtras.h"
1917#include " llvm/ADT/StringRef.h"
2018#include " llvm/Support/Error.h"
2119#include " llvm/Support/FormatVariadic.h"
2220#include " llvm/Support/JSON.h"
23- #include < string >
21+ #include < chrono >
2422#include < system_error>
25- #include < vector>
2623
2724namespace lldb_private {
2825
@@ -31,33 +28,27 @@ class TransportEOFError : public llvm::ErrorInfo<TransportEOFError> {
3128 static char ID;
3229
3330 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+ }
3535 std::error_code convertToErrorCode () const override {
36- return std::make_error_code (std::errc::io_error );
36+ return llvm::inconvertibleErrorCode ( );
3737 }
3838};
3939
40- class TransportUnhandledContentsError
41- : public llvm::ErrorInfo<TransportUnhandledContentsError> {
40+ class TransportTimeoutError : public llvm ::ErrorInfo<TransportTimeoutError> {
4241public:
4342 static char ID;
4443
45- explicit TransportUnhandledContentsError (std::string unhandled_contents)
46- : m_unhandled_contents(unhandled_contents) {}
44+ TransportTimeoutError () = default ;
4745
4846 void log (llvm::raw_ostream &OS) const override {
49- OS << " transport EOF with unhandled contents " << m_unhandled_contents ;
47+ OS << " transport operation timed out " ;
5048 }
5149 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 );
5351 }
54-
55- const std::string &getUnhandledContents () const {
56- return m_unhandled_contents;
57- }
58-
59- private:
60- std::string m_unhandled_contents;
6152};
6253
6354class TransportInvalidError : public llvm ::ErrorInfo<TransportInvalidError> {
@@ -77,11 +68,6 @@ class TransportInvalidError : public llvm::ErrorInfo<TransportInvalidError> {
7768// / A transport class that uses JSON for communication.
7869class JSONTransport {
7970public:
80- using ReadHandleUP = MainLoopBase::ReadHandleUP;
81- template <typename T>
82- using Callback =
83- llvm::unique_function<void (MainLoopBase &, const llvm::Expected<T>)>;
84-
8571 JSONTransport (lldb::IOObjectSP input, lldb::IOObjectSP output);
8672 virtual ~JSONTransport () = default ;
8773
@@ -97,69 +83,24 @@ class JSONTransport {
9783 return WriteImpl (message);
9884 }
9985
100- // / Registers the transport with the MainLoop .
86+ // / Reads the next message from the input stream .
10187 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);
14793 }
14894
14995protected:
150- template <typename ... Ts> inline auto Logv (const char *Fmt, Ts &&...Vals) {
151- Log (llvm::formatv (Fmt, std::forward<Ts>(Vals)...).str ());
152- }
15396 virtual void Log (llvm::StringRef message);
15497
15598 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 ;
157101
158102 lldb::IOObjectSP m_input;
159103 lldb::IOObjectSP m_output;
160- std::string m_buffer;
161-
162- static constexpr size_t kReadBufferSize = 1024 ;
163104};
164105
165106// / A transport class for JSON with a HTTP header.
@@ -170,13 +111,14 @@ class HTTPDelimitedJSONTransport : public JSONTransport {
170111 virtual ~HTTPDelimitedJSONTransport () = default ;
171112
172113protected:
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 " ;
180122};
181123
182124// / A transport class for JSON RPC.
@@ -187,8 +129,9 @@ class JSONRPCTransport : public JSONTransport {
187129 virtual ~JSONRPCTransport () = default ;
188130
189131protected:
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 ;
192135
193136 static constexpr llvm::StringLiteral kMessageSeparator = " \n " ;
194137};
0 commit comments