diff --git a/Userland/DevTools/HackStudio/LanguageServers/ClientConnection.h b/Userland/DevTools/HackStudio/LanguageServers/ClientConnection.h index 563d317ac5..cba8fadb94 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/ClientConnection.h +++ b/Userland/DevTools/HackStudio/LanguageServers/ClientConnection.h @@ -20,8 +20,7 @@ namespace LanguageServers { class ClientConnection : public IPC::ClientConnection - , public LanguageServerEndpoint { - +{ public: explicit ClientConnection(NonnullRefPtr, int client_id); ~ClientConnection() override; diff --git a/Userland/DevTools/IPCCompiler/main.cpp b/Userland/DevTools/IPCCompiler/main.cpp index 82d77fd2f2..5b35a4942b 100644 --- a/Userland/DevTools/IPCCompiler/main.cpp +++ b/Userland/DevTools/IPCCompiler/main.cpp @@ -60,6 +60,25 @@ static String snake_case(String const& identifier) return builder.to_string(); } +bool is_primitive_type(String const& type) +{ + return (type == "u8" || type == "i8" || type == "u16" || type == "i16" + || type == "u32" || type == "i32" || type == "bool" || type == "double" + || type == "float" || type == "int" || type == "unsigned" || type == "unsigned int"); +} + +String message_name(String const& endpoint, String& message, bool is_response) +{ + StringBuilder builder; + builder.append("Messages::"); + builder.append(endpoint); + builder.append("::"); + builder.append(message); + if (is_response) + builder.append("Response"); + return builder.to_string(); +} + int main(int argc, char** argv) { if (argc != 2) { @@ -231,10 +250,11 @@ int main(int argc, char** argv) #include #include #include +#include #include #include #include -#include +#include #include #include )~~~"); @@ -329,6 +349,9 @@ public: message_generator.append(R"~~~( @message.name@(decltype(nullptr)) : m_ipc_message_valid(false) { } + @message.name@(@message.name@ const&) = default; + @message.name@(@message.name@&&) = default; + @message.name@& operator=(@message.name@ const&) = default; @message.constructor@ virtual ~@message.name@() override {} @@ -452,15 +475,109 @@ private: )~~~"); endpoint_generator.append(R"~~~( -class @endpoint.name@Endpoint : public IPC::Endpoint { +template +class @endpoint.name@Proxy { public: - @endpoint.name@Endpoint() { } - virtual ~@endpoint.name@Endpoint() override { } + // Used to disambiguate the constructor call. + struct Tag { }; + + @endpoint.name@Proxy(IPC::Connection& connection, Tag) + : m_connection(connection) + { } +)~~~"); + + for (auto& message : endpoint.messages) { + auto message_generator = endpoint_generator.fork(); + + auto do_implement_proxy = [&](String const& name, Vector const& parameters, bool is_synchronous) { + String return_type = "void"; + if (is_synchronous && !message.outputs.is_empty()) + return_type = message_name(endpoint.name, message.name, true); + message_generator.set("message.name", message.name); + message_generator.set("message.complex_return_type", return_type); + message_generator.set("async_prefix_maybe", is_synchronous ? "" : "async_"); + + message_generator.set("handler_name", snake_case(name)); + message_generator.append(R"~~~( + @message.complex_return_type@ @async_prefix_maybe@@handler_name@()~~~"); + + for (size_t i = 0; i < parameters.size(); ++i) { + auto& parameter = parameters[i]; + auto argument_generator = message_generator.fork(); + argument_generator.set("argument.type", parameter.type); + argument_generator.set("argument.name", parameter.name); + argument_generator.append("@argument.type@ @argument.name@"); + if (i != parameters.size() - 1) + argument_generator.append(", "); + } + + message_generator.append(") {"); + + if (is_synchronous) { + if (return_type != "void") { + message_generator.append(R"~~~( + return move(*)~~~"); + } else{ + message_generator.append(R"~~~( + )~~~"); + } + + message_generator.append("m_connection.template send_sync("); + } else { + message_generator.append(R"~~~( + m_connection.post_message(Messages::@endpoint.name@::@message.name@ { )~~~"); + } + + for (size_t i = 0; i < parameters.size(); ++i) { + auto& parameter = parameters[i]; + auto argument_generator = message_generator.fork(); + argument_generator.set("argument.name", parameter.name); + if (is_primitive_type(parameters[i].type)) + argument_generator.append("@argument.name@"); + else + argument_generator.append("move(@argument.name@)"); + if (i != parameters.size() - 1) + argument_generator.append(", "); + } + + if (is_synchronous) { + if (return_type != "void") { + message_generator.append(")"); + } + + message_generator.append(R"~~~(); + } +)~~~"); + } else { + message_generator.append(R"~~~( }); + } +)~~~"); + } + }; + + do_implement_proxy(message.name, message.inputs, message.is_synchronous); + if (message.is_synchronous) + do_implement_proxy(message.name, message.inputs, false); + } + + endpoint_generator.append(R"~~~( +private: + IPC::Connection& m_connection; +}; +)~~~"); + + endpoint_generator.append(R"~~~( +template +class @endpoint.name@Proxy; +class @endpoint.name@Stub; + +class @endpoint.name@Endpoint { +public: + template + using Proxy = @endpoint.name@Proxy; + using Stub = @endpoint.name@Stub; static u32 static_magic() { return @endpoint.magic@; } - virtual u32 magic() const override { return @endpoint.magic@; } - static String static_name() { return "@endpoint.name@"; } - virtual String name() const override { return "@endpoint.name@"; } static OwnPtr decode_message(ReadonlyBytes buffer, int sockfd) { @@ -550,6 +667,16 @@ public: return message; } +}; + +class @endpoint.name@Stub : public IPC::Stub { +public: + @endpoint.name@Stub() { } + virtual ~@endpoint.name@Stub() override { } + + virtual u32 magic() const override { return @endpoint.magic@; } + virtual String name() const override { return "@endpoint.name@"; } + virtual OwnPtr handle(const IPC::Message& message) override { switch (message.message_id()) { @@ -619,15 +746,8 @@ public: auto do_handle_message_decl = [&](String const& name, Vector const& parameters, bool is_response) { String return_type = "void"; - if (message.is_synchronous && !message.outputs.is_empty() && !is_response) { - StringBuilder builder; - builder.append("Messages::"); - builder.append(endpoint.name); - builder.append("::"); - builder.append(message.name); - builder.append("Response"); - return_type = builder.to_string(); - } + if (message.is_synchronous && !message.outputs.is_empty() && !is_response) + return_type = message_name(endpoint.name, message.name, true); message_generator.set("message.complex_return_type", return_type); message_generator.set("handler_name", snake_case(name)); @@ -637,11 +757,7 @@ public: auto make_argument_type = [](String const& type) { StringBuilder builder; - bool const_ref = true; - if (type == "u8" || type == "i8" || type == "u16" || type == "i16" - || type == "u32" || type == "i32" || type == "bool" || type == "double" - || type == "float" || type == "int" || type == "unsigned" || type == "unsigned int") - const_ref = false; + bool const_ref = !is_primitive_type(type); builder.append(type); if (const_ref) diff --git a/Userland/Libraries/LibIPC/CMakeLists.txt b/Userland/Libraries/LibIPC/CMakeLists.txt index ea1a23640e..d72e4d7fb5 100644 --- a/Userland/Libraries/LibIPC/CMakeLists.txt +++ b/Userland/Libraries/LibIPC/CMakeLists.txt @@ -1,8 +1,8 @@ set(SOURCES Decoder.cpp Encoder.cpp - Endpoint.cpp Message.cpp + Stub.cpp ) serenity_lib(LibIPC ipc) diff --git a/Userland/Libraries/LibIPC/ClientConnection.h b/Userland/Libraries/LibIPC/ClientConnection.h index 6d507e79ac..77eea2548a 100644 --- a/Userland/Libraries/LibIPC/ClientConnection.h +++ b/Userland/Libraries/LibIPC/ClientConnection.h @@ -17,10 +17,13 @@ NonnullRefPtr new_client_connection(Args&&... args) } template -class ClientConnection : public Connection { +class ClientConnection : public Connection, public ServerEndpoint::Stub { public: - ClientConnection(ServerEndpoint& endpoint, NonnullRefPtr socket, int client_id) - : IPC::Connection(endpoint, move(socket)) + using ClientProxy = typename ClientEndpoint::Proxy; + using ServerStub = typename ServerEndpoint::Stub; + + ClientConnection(ServerStub& stub, NonnullRefPtr socket, int client_id) + : IPC::Connection(stub, move(socket)) , m_client_id(client_id) { VERIFY(this->socket().is_connected()); diff --git a/Userland/Libraries/LibIPC/Connection.h b/Userland/Libraries/LibIPC/Connection.h index 260919ad7b..a859037ca8 100644 --- a/Userland/Libraries/LibIPC/Connection.h +++ b/Userland/Libraries/LibIPC/Connection.h @@ -28,8 +28,11 @@ namespace IPC { template class Connection : public Core::Object { public: - Connection(LocalEndpoint& local_endpoint, NonnullRefPtr socket) - : m_local_endpoint(local_endpoint) + using LocalStub = typename LocalEndpoint::Stub; + using PeerProxy = typename PeerEndpoint::Proxy; + + Connection(LocalStub& local_stub, NonnullRefPtr socket) + : m_local_stub(local_stub) , m_socket(move(socket)) , m_notifier(Core::Notifier::construct(m_socket->fd(), Core::Notifier::Read, this)) { @@ -248,13 +251,13 @@ protected: auto messages = move(m_unprocessed_messages); for (auto& message : messages) { if (message.endpoint_magic() == LocalEndpoint::static_magic()) - if (auto response = m_local_endpoint.handle(message)) + if (auto response = m_local_stub.handle(message)) post_message(*response); } } protected: - LocalEndpoint& m_local_endpoint; + LocalStub& m_local_stub; NonnullRefPtr m_socket; RefPtr m_responsiveness_timer; diff --git a/Userland/Libraries/LibIPC/ServerConnection.h b/Userland/Libraries/LibIPC/ServerConnection.h index 20010a9f82..bd6cc0dbcd 100644 --- a/Userland/Libraries/LibIPC/ServerConnection.h +++ b/Userland/Libraries/LibIPC/ServerConnection.h @@ -11,9 +11,12 @@ namespace IPC { template -class ServerConnection : public IPC::Connection { +class ServerConnection : public IPC::Connection, public ClientEndpoint::Stub { public: - ServerConnection(ClientEndpoint& local_endpoint, const StringView& address) + using ClientStub = typename ClientEndpoint::Stub; + using ServerProxy = typename ServerEndpoint::Proxy; + + ServerConnection(ClientStub& local_endpoint, const StringView& address) : Connection(local_endpoint, Core::LocalSocket::construct()) { // We want to rate-limit our clients diff --git a/Userland/Libraries/LibIPC/Endpoint.cpp b/Userland/Libraries/LibIPC/Stub.cpp similarity index 67% rename from Userland/Libraries/LibIPC/Endpoint.cpp rename to Userland/Libraries/LibIPC/Stub.cpp index 77976eee8e..4eca25a720 100644 --- a/Userland/Libraries/LibIPC/Endpoint.cpp +++ b/Userland/Libraries/LibIPC/Stub.cpp @@ -4,15 +4,15 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include namespace IPC { -Endpoint::Endpoint() +Stub::Stub() { } -Endpoint::~Endpoint() +Stub::~Stub() { } diff --git a/Userland/Libraries/LibIPC/Endpoint.h b/Userland/Libraries/LibIPC/Stub.h similarity index 88% rename from Userland/Libraries/LibIPC/Endpoint.h rename to Userland/Libraries/LibIPC/Stub.h index 74184c8a80..a4ac5aec21 100644 --- a/Userland/Libraries/LibIPC/Endpoint.h +++ b/Userland/Libraries/LibIPC/Stub.h @@ -18,16 +18,16 @@ namespace IPC { class Message; class MessageBuffer; -class Endpoint { +class Stub { public: - virtual ~Endpoint(); + virtual ~Stub(); virtual u32 magic() const = 0; virtual String name() const = 0; virtual OwnPtr handle(const Message&) = 0; protected: - Endpoint(); + Stub(); private: String m_name; diff --git a/Userland/Services/AudioServer/ClientConnection.h b/Userland/Services/AudioServer/ClientConnection.h index 5d79155e25..1a66f4bf70 100644 --- a/Userland/Services/AudioServer/ClientConnection.h +++ b/Userland/Services/AudioServer/ClientConnection.h @@ -21,7 +21,7 @@ class BufferQueue; class Mixer; class ClientConnection final : public IPC::ClientConnection - , public AudioServerEndpoint { +{ C_OBJECT(ClientConnection) public: explicit ClientConnection(NonnullRefPtr, int client_id, Mixer& mixer); diff --git a/Userland/Services/Clipboard/ClientConnection.h b/Userland/Services/Clipboard/ClientConnection.h index 70d33da56d..1bf0055b2d 100644 --- a/Userland/Services/Clipboard/ClientConnection.h +++ b/Userland/Services/Clipboard/ClientConnection.h @@ -15,8 +15,7 @@ namespace Clipboard { class ClientConnection final : public IPC::ClientConnection - , public ClipboardServerEndpoint { - +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/ImageDecoder/ClientConnection.h b/Userland/Services/ImageDecoder/ClientConnection.h index 950b799bac..89d6ef856d 100644 --- a/Userland/Services/ImageDecoder/ClientConnection.h +++ b/Userland/Services/ImageDecoder/ClientConnection.h @@ -17,7 +17,7 @@ namespace ImageDecoder { class ClientConnection final : public IPC::ClientConnection - , public ImageDecoderServerEndpoint { +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/LaunchServer/ClientConnection.h b/Userland/Services/LaunchServer/ClientConnection.h index e14c2a61b9..c4e7c6ad57 100644 --- a/Userland/Services/LaunchServer/ClientConnection.h +++ b/Userland/Services/LaunchServer/ClientConnection.h @@ -13,7 +13,7 @@ namespace LaunchServer { class ClientConnection final : public IPC::ClientConnection - , public LaunchServerEndpoint { +{ C_OBJECT(ClientConnection) public: ~ClientConnection() override; diff --git a/Userland/Services/LookupServer/ClientConnection.h b/Userland/Services/LookupServer/ClientConnection.h index 3289e36be0..50f7316c50 100644 --- a/Userland/Services/LookupServer/ClientConnection.h +++ b/Userland/Services/LookupServer/ClientConnection.h @@ -15,8 +15,7 @@ namespace LookupServer { class ClientConnection final : public IPC::ClientConnection - , public LookupServerEndpoint { - +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/NotificationServer/ClientConnection.h b/Userland/Services/NotificationServer/ClientConnection.h index faf2090737..2abe843cce 100644 --- a/Userland/Services/NotificationServer/ClientConnection.h +++ b/Userland/Services/NotificationServer/ClientConnection.h @@ -13,7 +13,7 @@ namespace NotificationServer { class ClientConnection final : public IPC::ClientConnection - , public NotificationServerEndpoint { +{ C_OBJECT(ClientConnection) public: ~ClientConnection() override; diff --git a/Userland/Services/RequestServer/ClientConnection.h b/Userland/Services/RequestServer/ClientConnection.h index 877c92e628..6bfcd6e172 100644 --- a/Userland/Services/RequestServer/ClientConnection.h +++ b/Userland/Services/RequestServer/ClientConnection.h @@ -16,7 +16,7 @@ namespace RequestServer { class ClientConnection final : public IPC::ClientConnection - , public RequestServerEndpoint { +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/SymbolServer/ClientConnection.h b/Userland/Services/SymbolServer/ClientConnection.h index 900aaf3301..ea6132983c 100644 --- a/Userland/Services/SymbolServer/ClientConnection.h +++ b/Userland/Services/SymbolServer/ClientConnection.h @@ -17,7 +17,7 @@ namespace SymbolServer { class ClientConnection final : public IPC::ClientConnection - , public SymbolServerEndpoint { +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/WebContent/ClientConnection.h b/Userland/Services/WebContent/ClientConnection.h index f9cf68fb2c..cfc0ea691d 100644 --- a/Userland/Services/WebContent/ClientConnection.h +++ b/Userland/Services/WebContent/ClientConnection.h @@ -20,7 +20,7 @@ namespace WebContent { class ClientConnection final : public IPC::ClientConnection - , public WebContentServerEndpoint { +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/WebSocket/ClientConnection.h b/Userland/Services/WebSocket/ClientConnection.h index e9b6f327ac..65720e2f99 100644 --- a/Userland/Services/WebSocket/ClientConnection.h +++ b/Userland/Services/WebSocket/ClientConnection.h @@ -16,7 +16,7 @@ namespace WebSocket { class ClientConnection final : public IPC::ClientConnection - , public WebSocketServerEndpoint { +{ C_OBJECT(ClientConnection); public: diff --git a/Userland/Services/WindowServer/ClientConnection.h b/Userland/Services/WindowServer/ClientConnection.h index d04cf2f309..3d8a32a2a2 100644 --- a/Userland/Services/WindowServer/ClientConnection.h +++ b/Userland/Services/WindowServer/ClientConnection.h @@ -29,7 +29,7 @@ class WMClientConnection; class ClientConnection final : public IPC::ClientConnection - , public WindowServerEndpoint { +{ C_OBJECT(ClientConnection) public: ~ClientConnection() override; diff --git a/Userland/Services/WindowServer/WMClientConnection.h b/Userland/Services/WindowServer/WMClientConnection.h index 561acd6f77..1e7ff649fc 100644 --- a/Userland/Services/WindowServer/WMClientConnection.h +++ b/Userland/Services/WindowServer/WMClientConnection.h @@ -16,7 +16,7 @@ namespace WindowServer { class WMClientConnection final : public IPC::ClientConnection - , public WindowManagerServerEndpoint { +{ C_OBJECT(WMClientConnection) public: