From 277ffa2881d4073a660490f959cb58ad0dcb3f82 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Sep 2016 10:01:44 +0200 Subject: server-mode: Move constants for server mode into its own file This removes some duplication and makes it easier to reuse the vocabulary. --- Source/cmServer.cxx | 64 ++++++++++++++++++++----------------------- Source/cmServerConnection.cxx | 5 ++-- Source/cmServerDictionary.h | 47 +++++++++++++++++++++++++++++++ Source/cmServerProtocol.cxx | 12 ++------ 4 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 Source/cmServerDictionary.h diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 56cd7ba..b0675da 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -14,6 +14,7 @@ #include "cmServer.h" #include "cmServerConnection.h" +#include "cmServerDictionary.h" #include "cmServerProtocol.h" #include "cmSystemTools.h" #include "cmVersionMacros.h" @@ -28,19 +29,6 @@ #include #include -static const std::string kTYPE_KEY = "type"; -static const std::string kCOOKIE_KEY = "cookie"; -static const std::string kREPLY_TO_KEY = "inReplyTo"; -static const std::string kERROR_MESSAGE_KEY = "errorMessage"; - -static const std::string kERROR_TYPE = "error"; -static const std::string kREPLY_TYPE = "reply"; -static const std::string kPROGRESS_TYPE = "progress"; -static const std::string kMESSAGE_TYPE = "message"; - -static const std::string kSTART_MAGIC = "[== CMake Server ==["; -static const std::string kEND_MAGIC = "]== CMake Server ==]"; - class cmServer::DebugInfo { public: @@ -144,16 +132,16 @@ void cmServer::PrintHello() const Json::Value hello = Json::objectValue; hello[kTYPE_KEY] = "hello"; - Json::Value& protocolVersions = hello["supportedProtocolVersions"] = + Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] = Json::arrayValue; for (auto const& proto : this->SupportedProtocols) { auto version = proto->ProtocolVersion(); Json::Value tmp = Json::objectValue; - tmp["major"] = version.first; - tmp["minor"] = version.second; + tmp[kMAJOR_KEY] = version.first; + tmp[kMINOR_KEY] = version.second; if (proto->IsExperimental()) { - tmp["experimental"] = true; + tmp[kIS_EXPERIMENTAL_KEY] = true; } protocolVersions.append(tmp); } @@ -193,31 +181,37 @@ void cmServer::reportMessage(const char* msg, const char* title, cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) { - if (request.Type != "handshake") - return request.ReportError("Waiting for type \"handshake\"."); + if (request.Type != kHANDSHAKE_TYPE) + return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE + + "\"."); - Json::Value requestedProtocolVersion = request.Data["protocolVersion"]; + Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY]; if (requestedProtocolVersion.isNull()) - return request.ReportError( - "\"protocolVersion\" is required for \"handshake\"."); + return request.ReportError("\"" + kPROTOCOL_VERSION_KEY + + "\" is required for \"" + kHANDSHAKE_TYPE + + "\"."); if (!requestedProtocolVersion.isObject()) - return request.ReportError("\"protocolVersion\" must be a JSON object."); + return request.ReportError("\"" + kPROTOCOL_VERSION_KEY + + "\" must be a JSON object."); - Json::Value majorValue = requestedProtocolVersion["major"]; + Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY]; if (!majorValue.isInt()) - return request.ReportError("\"major\" must be set and an integer."); + return request.ReportError("\"" + kMAJOR_KEY + + "\" must be set and an integer."); - Json::Value minorValue = requestedProtocolVersion["minor"]; + Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY]; if (!minorValue.isNull() && !minorValue.isInt()) - return request.ReportError("\"minor\" must be unset or an integer."); + return request.ReportError("\"" + kMINOR_KEY + + "\" must be unset or an integer."); const int major = majorValue.asInt(); const int minor = minorValue.isNull() ? -1 : minorValue.asInt(); if (major < 0) - return request.ReportError("\"major\" must be >= 0."); + return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0."); if (!minorValue.isNull() && minor < 0) - return request.ReportError("\"minor\" must be >= 0 when set."); + return request.ReportError("\"" + kMINOR_KEY + + "\" must be >= 0 when set."); this->Protocol = this->FindMatchingProtocol(this->SupportedProtocols, major, minor); @@ -311,10 +305,10 @@ void cmServer::WriteProgress(const cmServerRequest& request, int min, obj[kTYPE_KEY] = kPROGRESS_TYPE; obj[kREPLY_TO_KEY] = request.Type; obj[kCOOKIE_KEY] = request.Cookie; - obj["progressMessage"] = message; - obj["progressMinimum"] = min; - obj["progressMaximum"] = max; - obj["progressCurrent"] = current; + obj[kPROGRESS_MESSAGE_KEY] = message; + obj[kPROGRESS_MINIMUM_KEY] = min; + obj[kPROGRESS_MAXIMUM_KEY] = max; + obj[kPROGRESS_CURRENT_KEY] = current; this->WriteJsonObject(obj, nullptr); } @@ -330,9 +324,9 @@ void cmServer::WriteMessage(const cmServerRequest& request, obj[kTYPE_KEY] = kMESSAGE_TYPE; obj[kREPLY_TO_KEY] = request.Type; obj[kCOOKIE_KEY] = request.Cookie; - obj["message"] = message; + obj[kMESSAGE_KEY] = message; if (!title.empty()) { - obj["title"] = title; + obj[kTITLE_KEY] = title; } WriteJsonObject(obj, nullptr); diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 398e250..112cafd 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -13,15 +13,14 @@ #include "cmServerConnection.h" +#include "cmServerDictionary.h" + #include #include namespace { -static const std::string kSTART_MAGIC = "[== CMake Server ==["; -static const std::string kEND_MAGIC = "]== CMake Server ==]"; - struct write_req_t { uv_write_t req; diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h new file mode 100644 index 0000000..379c94d --- /dev/null +++ b/Source/cmServerDictionary.h @@ -0,0 +1,47 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2016 Tobias Hunger + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#pragma once + +#include + +// Vocabulary: + +static const std::string kERROR_TYPE = "error"; +static const std::string kHANDSHAKE_TYPE = "handshake"; +static const std::string kMESSAGE_TYPE = "message"; +static const std::string kPROGRESS_TYPE = "progress"; +static const std::string kREPLY_TYPE = "reply"; + +static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; +static const std::string kCOOKIE_KEY = "cookie"; +static const std::string kERROR_MESSAGE_KEY = "errorMessage"; +static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator"; +static const std::string kGENERATOR_KEY = "generator"; +static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental"; +static const std::string kMAJOR_KEY = "major"; +static const std::string kMESSAGE_KEY = "message"; +static const std::string kMINOR_KEY = "minor"; +static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent"; +static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum"; +static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage"; +static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum"; +static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion"; +static const std::string kREPLY_TO_KEY = "inReplyTo"; +static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory"; +static const std::string kSUPPORTED_PROTOCOL_VERSIONS = + "supportedProtocolVersions"; +static const std::string kTITLE_KEY = "title"; +static const std::string kTYPE_KEY = "type"; + +static const std::string kSTART_MAGIC = "[== CMake Server ==["; +static const std::string kEND_MAGIC = "]== CMake Server ==]"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 26942d3..030b0fd 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -14,23 +14,17 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmServer.h" +#include "cmServerDictionary.h" #include "cmSystemTools.h" #include "cmake.h" +#include "cmServerDictionary.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cm_jsoncpp_reader.h" #include "cm_jsoncpp_value.h" #endif -// Vocabulary: - -static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; -static const std::string kCOOKIE_KEY = "cookie"; -static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator"; -static const std::string kGENERATOR_KEY = "generator"; -static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory"; -static const std::string kTYPE_KEY = "type"; - cmServerRequest::cmServerRequest(cmServer* server, const std::string& t, const std::string& c, const Json::Value& d) : Type(t) -- cgit v0.12 From cc576c2c7f3272ec5370dc3cb45838c20d1837f9 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Sep 2016 12:50:23 +0200 Subject: server-mode: Pass server into cmServerProtocol The information will be needed to send signals. --- Source/cmServer.cxx | 2 +- Source/cmServer.h | 3 ++- Source/cmServerProtocol.cxx | 5 ++++- Source/cmServerProtocol.h | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index b0675da..f7e5e3b 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -220,7 +220,7 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) } std::string errorMessage; - if (!this->Protocol->Activate(request, &errorMessage)) { + if (!this->Protocol->Activate(this, request, &errorMessage)) { this->Protocol = CM_NULLPTR; return request.ReportError("Failed to activate protocol version: " + errorMessage); diff --git a/Source/cmServer.h b/Source/cmServer.h index dde5333..433b2ac 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -95,6 +95,7 @@ private: mutable bool Writing = false; - friend class cmServerRequest; friend class cmServerConnection; + friend class cmServerProtocol; + friend class cmServerRequest; }; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 030b0fd..16a6374 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -109,9 +109,12 @@ Json::Value cmServerResponse::Data() const return this->m_Data; } -bool cmServerProtocol::Activate(const cmServerRequest& request, +bool cmServerProtocol::Activate(cmServer* server, + const cmServerRequest& request, std::string* errorMessage) { + assert(server); + this->m_Server = server; this->m_CMakeInstance = std::make_unique(); const bool result = this->DoActivate(request, errorMessage); if (!result) diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index bab949b..92c8162 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -87,7 +87,8 @@ public: virtual bool IsExperimental() const = 0; virtual const cmServerResponse Process(const cmServerRequest& request) = 0; - bool Activate(const cmServerRequest& request, std::string* errorMessage); + bool Activate(cmServer* server, const cmServerRequest& request, + std::string* errorMessage); protected: cmake* CMakeInstance() const; @@ -97,6 +98,7 @@ protected: private: std::unique_ptr m_CMakeInstance; + cmServer* m_Server = nullptr; // not owned! friend class cmServer; }; -- cgit v0.12 From e22d30e25a264c309bd819edde3eacb1184da800 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 9 Sep 2016 10:01:45 +0200 Subject: server-mode: Allow for sending signals Enable the server to send signals. --- Help/manual/cmake-server.7.rst | 8 ++++++++ Source/cmServer.cxx | 13 +++++++++++++ Source/cmServer.h | 1 + Source/cmServerDictionary.h | 2 ++ Source/cmServerProtocol.cxx | 7 +++++++ Source/cmServerProtocol.h | 2 ++ 6 files changed, 33 insertions(+) diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst index 00ffcd1..61d6896 100644 --- a/Help/manual/cmake-server.7.rst +++ b/Help/manual/cmake-server.7.rst @@ -186,6 +186,14 @@ Example:: ]== CMake Server ==] +Type "signal" +^^^^^^^^^^^^^ + +The server can send signals when it detects changes in the system state. Signals +are of type "signal", have an empty "cookie" and "inReplyTo" field and always +have a "name" set to show which signal was sent. + + Specific Message Types ---------------------- diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index f7e5e3b..d5dac4e 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -343,6 +343,19 @@ void cmServer::WriteParseError(const std::string& message) const this->WriteJsonObject(obj, nullptr); } +void cmServer::WriteSignal(const std::string& name, + const Json::Value& data) const +{ + assert(data.isObject()); + Json::Value obj = data; + obj[kTYPE_KEY] = kSIGNAL_TYPE; + obj[kREPLY_TO_KEY] = ""; + obj[kCOOKIE_KEY] = ""; + obj[kNAME_KEY] = name; + + WriteJsonObject(obj, nullptr); +} + void cmServer::WriteResponse(const cmServerResponse& response, const DebugInfo* debug) const { diff --git a/Source/cmServer.h b/Source/cmServer.h index 433b2ac..849e5c5 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -63,6 +63,7 @@ private: void WriteResponse(const cmServerResponse& response, const DebugInfo* debug) const; void WriteParseError(const std::string& message) const; + void WriteSignal(const std::string& name, const Json::Value& obj) const; void WriteJsonObject(Json::Value const& jsonValue, const DebugInfo* debug) const; diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 379c94d..156ade2 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -21,6 +21,7 @@ static const std::string kHANDSHAKE_TYPE = "handshake"; static const std::string kMESSAGE_TYPE = "message"; static const std::string kPROGRESS_TYPE = "progress"; static const std::string kREPLY_TYPE = "reply"; +static const std::string kSIGNAL_TYPE = "signal"; static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory"; static const std::string kCOOKIE_KEY = "cookie"; @@ -31,6 +32,7 @@ static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental"; static const std::string kMAJOR_KEY = "major"; static const std::string kMESSAGE_KEY = "message"; static const std::string kMINOR_KEY = "minor"; +static const std::string kNAME_KEY = "name"; static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent"; static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum"; static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 16a6374..e42b18a 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -122,6 +122,13 @@ bool cmServerProtocol::Activate(cmServer* server, return result; } +void cmServerProtocol::SendSignal(const std::string& name, + const Json::Value& data) const +{ + if (this->m_Server) + this->m_Server->WriteSignal(name, data); +} + cmake* cmServerProtocol::CMakeInstance() const { return this->m_CMakeInstance.get(); diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 92c8162..0383dfe 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -90,6 +90,8 @@ public: bool Activate(cmServer* server, const cmServerRequest& request, std::string* errorMessage); + void SendSignal(const std::string& name, const Json::Value& data) const; + protected: cmake* CMakeInstance() const; // Implement protocol specific activation tasks here. Called from Activate(). -- cgit v0.12