1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include "cm_jsoncpp_value.h"
#include "cm_thread.hxx"
#include "cm_uv.h"
#include "cmUVHandlePtr.h"
#include <memory> // IWYU pragma: keep
#include <string>
#include <vector>
class cmConnection;
class cmFileMonitor;
class cmServerProtocol;
class cmServerRequest;
class cmServerResponse;
/***
* This essentially hold and manages a libuv event queue and responds to
* messages
* on any of its connections.
*/
class cmServerBase
{
public:
cmServerBase(cmConnection* connection);
virtual ~cmServerBase();
virtual void AddNewConnection(cmConnection* ownedConnection);
/***
* The main override responsible for tailoring behavior towards
* whatever the given server is supposed to do
*
* This should almost always be called by the given connections
* directly.
*
* @param connection The connection the request was received on
* @param request The actual request
*/
virtual void ProcessRequest(cmConnection* connection,
const std::string& request) = 0;
virtual void OnConnected(cmConnection* connection);
/***
* Start a dedicated thread. If this is used to start the server, it will
* join on the
* servers dtor.
*/
virtual bool StartServeThread();
virtual bool Serve(std::string* errorMessage);
virtual void OnServeStart();
virtual void StartShutDown();
virtual bool OnSignal(int signum);
uv_loop_t* GetLoop();
void Close();
void OnDisconnect(cmConnection* pConnection);
protected:
mutable cm::shared_mutex ConnectionsMutex;
std::vector<std::unique_ptr<cmConnection>> Connections;
bool ServeThreadRunning = false;
uv_thread_t ServeThread;
cm::uv_async_ptr ShutdownSignal;
#ifndef NDEBUG
public:
// When the server starts it will mark down it's current thread ID,
// which is useful in other contexts to just assert that operations
// are performed on that same thread.
uv_thread_t ServeThreadId = {};
protected:
#endif
uv_loop_t Loop;
cm::uv_signal_ptr SIGINTHandler;
cm::uv_signal_ptr SIGHUPHandler;
};
class cmServer : public cmServerBase
{
CM_DISABLE_COPY(cmServer)
public:
class DebugInfo;
cmServer(cmConnection* conn, bool supportExperimental);
~cmServer() override;
bool Serve(std::string* errorMessage) override;
cmFileMonitor* FileMonitor() const;
private:
void RegisterProtocol(cmServerProtocol* protocol);
// Callbacks from cmServerConnection:
void ProcessRequest(cmConnection* connection,
const std::string& request) override;
std::shared_ptr<cmFileMonitor> fileMonitor;
public:
void OnServeStart() override;
void StartShutDown() override;
public:
void OnConnected(cmConnection* connection) override;
private:
static void reportProgress(const char* msg, float progress, void* data);
static void reportMessage(const char* msg, const char* title, bool& cancel,
void* data);
// Handle requests:
cmServerResponse SetProtocolVersion(const cmServerRequest& request);
void PrintHello(cmConnection* connection) const;
// Write responses:
void WriteProgress(const cmServerRequest& request, int min, int current,
int max, const std::string& message) const;
void WriteMessage(const cmServerRequest& request, const std::string& message,
const std::string& title) const;
void WriteResponse(cmConnection* connection,
const cmServerResponse& response,
const DebugInfo* debug) const;
void WriteParseError(cmConnection* connection,
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;
void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue,
const DebugInfo* debug) const;
static cmServerProtocol* FindMatchingProtocol(
const std::vector<cmServerProtocol*>& protocols, int major, int minor);
const bool SupportExperimental;
cmServerProtocol* Protocol = nullptr;
std::vector<cmServerProtocol*> SupportedProtocols;
friend class cmServerProtocol;
friend class cmServerRequest;
};
|