summaryrefslogtreecommitdiffstats
path: root/Source/cmServer.cxx
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@qt.io>2016-09-09 08:01:44 (GMT)
committerBrad King <brad.king@kitware.com>2016-09-22 12:06:38 (GMT)
commit1d601c6cb978a3b6b6143fdf64e284fb3a098d1e (patch)
tree1f274c04ba934cbc06cff9b8f9d33b7defbc7212 /Source/cmServer.cxx
parent2c2ffd3874f749979d723d7a788d45e3830952d6 (diff)
downloadCMake-1d601c6cb978a3b6b6143fdf64e284fb3a098d1e.zip
CMake-1d601c6cb978a3b6b6143fdf64e284fb3a098d1e.tar.gz
CMake-1d601c6cb978a3b6b6143fdf64e284fb3a098d1e.tar.bz2
server-mode: Introduce cmServerConnection
Use it to split pipe and stdin/out handling out of cmServer itself. The server will shut down when it looses its connection to the client. This has the nice property that a crashing client will cause the server to terminate as the OS will close the connection on behave of the client.
Diffstat (limited to 'Source/cmServer.cxx')
-rw-r--r--Source/cmServer.cxx145
1 files changed, 19 insertions, 126 deletions
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index be001a7..56cd7ba 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -13,6 +13,7 @@
#include "cmServer.h"
+#include "cmServerConnection.h"
#include "cmServerProtocol.h"
#include "cmSystemTools.h"
#include "cmVersionMacros.h"
@@ -40,57 +41,6 @@ static const std::string kMESSAGE_TYPE = "message";
static const std::string kSTART_MAGIC = "[== CMake Server ==[";
static const std::string kEND_MAGIC = "]== CMake Server ==]";
-typedef struct
-{
- uv_write_t req;
- uv_buf_t buf;
-} write_req_t;
-
-void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
-{
- (void)handle;
- *buf = uv_buf_init(static_cast<char*>(malloc(suggested_size)),
- static_cast<unsigned int>(suggested_size));
-}
-
-void free_write_req(uv_write_t* req)
-{
- write_req_t* wr = reinterpret_cast<write_req_t*>(req);
- free(wr->buf.base);
- free(wr);
-}
-
-void on_stdout_write(uv_write_t* req, int status)
-{
- (void)status;
- auto server = reinterpret_cast<cmServer*>(req->data);
- free_write_req(req);
- server->PopOne();
-}
-
-void write_data(uv_stream_t* dest, std::string content, uv_write_cb cb)
-{
- write_req_t* req = static_cast<write_req_t*>(malloc(sizeof(write_req_t)));
- req->req.data = dest->data;
- req->buf = uv_buf_init(static_cast<char*>(malloc(content.size())),
- static_cast<unsigned int>(content.size()));
- memcpy(req->buf.base, content.c_str(), content.size());
- uv_write(reinterpret_cast<uv_write_t*>(req), static_cast<uv_stream_t*>(dest),
- &req->buf, 1, cb);
-}
-
-void read_stdin(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
-{
- if (nread > 0) {
- auto server = reinterpret_cast<cmServer*>(stream->data);
- std::string result = std::string(buf->base, buf->base + nread);
- server->handleData(result);
- }
-
- if (buf->base)
- free(buf->base);
-}
-
class cmServer::DebugInfo
{
public:
@@ -105,9 +55,11 @@ public:
uint64_t StartTime;
};
-cmServer::cmServer(bool supportExperimental)
- : SupportExperimental(supportExperimental)
+cmServer::cmServer(cmServerConnection* conn, bool supportExperimental)
+ : Connection(conn)
+ , SupportExperimental(supportExperimental)
{
+ this->Connection->SetServer(this);
// Register supported protocols:
this->RegisterProtocol(new cmServerProtocol1_0);
}
@@ -118,18 +70,15 @@ cmServer::~cmServer()
return;
}
- uv_close(reinterpret_cast<uv_handle_t*>(this->InputStream), NULL);
- uv_close(reinterpret_cast<uv_handle_t*>(this->OutputStream), NULL);
- uv_loop_close(this->Loop);
-
for (cmServerProtocol* p : this->SupportedProtocols) {
delete p;
}
+
+ delete this->Connection;
}
void cmServer::PopOne()
{
- this->Writing = false;
if (this->Queue.empty()) {
return;
}
@@ -173,39 +122,6 @@ void cmServer::PopOne()
}
}
-void cmServer::handleData(const std::string& data)
-{
- this->DataBuffer += data;
-
- for (;;) {
- auto needle = this->DataBuffer.find('\n');
-
- if (needle == std::string::npos) {
- return;
- }
- std::string line = this->DataBuffer.substr(0, needle);
- const auto ls = line.size();
- if (ls > 1 && line.at(ls - 1) == '\r')
- line.erase(ls - 1, 1);
- this->DataBuffer.erase(this->DataBuffer.begin(),
- this->DataBuffer.begin() + needle + 1);
- if (line == kSTART_MAGIC) {
- this->JsonData.clear();
- continue;
- }
- if (line == kEND_MAGIC) {
- this->Queue.push_back(this->JsonData);
- this->JsonData.clear();
- if (!this->Writing) {
- this->PopOne();
- }
- } else {
- this->JsonData += line;
- this->JsonData += "\n";
- }
- }
-}
-
void cmServer::RegisterProtocol(cmServerProtocol* protocol)
{
if (protocol->IsExperimental() && !this->SupportExperimental) {
@@ -245,6 +161,12 @@ void cmServer::PrintHello() const
this->WriteJsonObject(hello, nullptr);
}
+void cmServer::QueueRequest(const std::string& request)
+{
+ this->Queue.push_back(request);
+ this->PopOne();
+}
+
void cmServer::reportProgress(const char* msg, float progress, void* data)
{
const cmServerRequest* request = static_cast<const cmServerRequest*>(data);
@@ -312,43 +234,16 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
return request.Reply(Json::objectValue);
}
-bool cmServer::Serve()
+bool cmServer::Serve(std::string* errorMessage)
{
if (this->SupportedProtocols.empty()) {
+ *errorMessage =
+ "No protocol versions defined. Maybe you need --experimental?";
return false;
}
assert(!this->Protocol);
- this->Loop = uv_default_loop();
-
- if (uv_guess_handle(1) == UV_TTY) {
- uv_tty_init(this->Loop, &this->Input.tty, 0, 1);
- uv_tty_set_mode(&this->Input.tty, UV_TTY_MODE_NORMAL);
- this->Input.tty.data = this;
- InputStream = reinterpret_cast<uv_stream_t*>(&this->Input.tty);
-
- uv_tty_init(this->Loop, &this->Output.tty, 1, 0);
- uv_tty_set_mode(&this->Output.tty, UV_TTY_MODE_NORMAL);
- this->Output.tty.data = this;
- OutputStream = reinterpret_cast<uv_stream_t*>(&this->Output.tty);
- } else {
- uv_pipe_init(this->Loop, &this->Input.pipe, 0);
- uv_pipe_open(&this->Input.pipe, 0);
- this->Input.pipe.data = this;
- InputStream = reinterpret_cast<uv_stream_t*>(&this->Input.pipe);
-
- uv_pipe_init(this->Loop, &this->Output.pipe, 0);
- uv_pipe_open(&this->Output.pipe, 1);
- this->Output.pipe.data = this;
- OutputStream = reinterpret_cast<uv_stream_t*>(&this->Output.pipe);
- }
-
- this->PrintHello();
-
- uv_read_start(this->InputStream, alloc_buffer, read_stdin);
-
- uv_run(this->Loop, UV_RUN_DEFAULT);
- return true;
+ return Connection->ProcessEvents(errorMessage);
}
void cmServer::WriteJsonObject(const Json::Value& jsonValue,
@@ -385,10 +280,8 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue,
}
}
- this->Writing = true;
- write_data(this->OutputStream, std::string("\n") + kSTART_MAGIC +
- std::string("\n") + result + kEND_MAGIC + std::string("\n"),
- on_stdout_write);
+ Connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") +
+ result + kEND_MAGIC + std::string("\n"));
}
cmServerProtocol* cmServer::FindMatchingProtocol(