diff options
Diffstat (limited to 'src/interfaces')
-rw-r--r-- | src/interfaces/README.md | 6 | ||||
-rw-r--r-- | src/interfaces/echo.cpp | 18 | ||||
-rw-r--r-- | src/interfaces/echo.h | 26 | ||||
-rw-r--r-- | src/interfaces/init.cpp | 17 | ||||
-rw-r--r-- | src/interfaces/init.h | 52 | ||||
-rw-r--r-- | src/interfaces/ipc.h | 71 |
6 files changed, 188 insertions, 2 deletions
diff --git a/src/interfaces/README.md b/src/interfaces/README.md index f77d172153..97167d5298 100644 --- a/src/interfaces/README.md +++ b/src/interfaces/README.md @@ -12,6 +12,8 @@ The following interfaces are defined here: * [`Handler`](handler.h) — returned by `handleEvent` methods on interfaces above and used to manage lifetimes of event handlers. -* [`Init`](init.h) — used by multiprocess code to access interfaces above on startup. Added in [#10102](https://github.com/bitcoin/bitcoin/pull/10102). +* [`Init`](init.h) — used by multiprocess code to access interfaces above on startup. Added in [#19160](https://github.com/bitcoin/bitcoin/pull/19160). -The interfaces above define boundaries between major components of bitcoin code (node, wallet, and gui), making it possible for them to run in different processes, and be tested, developed, and understood independently. These interfaces are not currently designed to be stable or to be used externally. +* [`Ipc`](ipc.h) — used by multiprocess code to access `Init` interface across processes. Added in [#19160](https://github.com/bitcoin/bitcoin/pull/19160). + +The interfaces above define boundaries between major components of bitcoin code (node, wallet, and gui), making it possible for them to run in [different processes](../../doc/multiprocess.md), and be tested, developed, and understood independently. These interfaces are not currently designed to be stable or to be used externally. diff --git a/src/interfaces/echo.cpp b/src/interfaces/echo.cpp new file mode 100644 index 0000000000..9bbb42217b --- /dev/null +++ b/src/interfaces/echo.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <interfaces/echo.h> + +#include <memory> + +namespace interfaces { +namespace { +class EchoImpl : public Echo +{ +public: + std::string echo(const std::string& echo) override { return echo; } +}; +} // namespace +std::unique_ptr<Echo> MakeEcho() { return std::make_unique<EchoImpl>(); } +} // namespace interfaces diff --git a/src/interfaces/echo.h b/src/interfaces/echo.h new file mode 100644 index 0000000000..5578d9d9e6 --- /dev/null +++ b/src/interfaces/echo.h @@ -0,0 +1,26 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_INTERFACES_ECHO_H +#define BITCOIN_INTERFACES_ECHO_H + +#include <memory> +#include <string> + +namespace interfaces { +//! Simple string echoing interface for testing. +class Echo +{ +public: + virtual ~Echo() {} + + //! Echo provided string. + virtual std::string echo(const std::string& echo) = 0; +}; + +//! Return implementation of Echo interface. +std::unique_ptr<Echo> MakeEcho(); +} // namespace interfaces + +#endif // BITCOIN_INTERFACES_ECHO_H diff --git a/src/interfaces/init.cpp b/src/interfaces/init.cpp new file mode 100644 index 0000000000..a3c949e616 --- /dev/null +++ b/src/interfaces/init.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <interfaces/chain.h> +#include <interfaces/echo.h> +#include <interfaces/init.h> +#include <interfaces/node.h> +#include <interfaces/wallet.h> + +namespace interfaces { +std::unique_ptr<Node> Init::makeNode() { return {}; } +std::unique_ptr<Chain> Init::makeChain() { return {}; } +std::unique_ptr<WalletClient> Init::makeWalletClient(Chain& chain) { return {}; } +std::unique_ptr<Echo> Init::makeEcho() { return {}; } +Ipc* Init::ipc() { return nullptr; } +} // namespace interfaces diff --git a/src/interfaces/init.h b/src/interfaces/init.h new file mode 100644 index 0000000000..2a38054a17 --- /dev/null +++ b/src/interfaces/init.h @@ -0,0 +1,52 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_INTERFACES_INIT_H +#define BITCOIN_INTERFACES_INIT_H + +#include <memory> + +struct NodeContext; + +namespace interfaces { +class Chain; +class Echo; +class Ipc; +class Node; +class WalletClient; + +//! Initial interface created when a process is first started, and used to give +//! and get access to other interfaces (Node, Chain, Wallet, etc). +//! +//! There is a different Init interface implementation for each process +//! (bitcoin-gui, bitcoin-node, bitcoin-wallet, bitcoind, bitcoin-qt) and each +//! implementation can implement the make methods for interfaces it supports. +//! The default make methods all return null. +class Init +{ +public: + virtual ~Init() = default; + virtual std::unique_ptr<Node> makeNode(); + virtual std::unique_ptr<Chain> makeChain(); + virtual std::unique_ptr<WalletClient> makeWalletClient(Chain& chain); + virtual std::unique_ptr<Echo> makeEcho(); + virtual Ipc* ipc(); +}; + +//! Return implementation of Init interface for the node process. If the argv +//! indicates that this is a child process spawned to handle requests from a +//! parent process, this blocks and handles requests, then returns null and a +//! status code to exit with. If this returns non-null, the caller can start up +//! normally and use the Init object to spawn and connect to other processes +//! while it is running. +std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status); + +//! Return implementation of Init interface for the wallet process. +std::unique_ptr<Init> MakeWalletInit(int argc, char* argv[], int& exit_status); + +//! Return implementation of Init interface for the gui process. +std::unique_ptr<Init> MakeGuiInit(int argc, char* argv[]); +} // namespace interfaces + +#endif // BITCOIN_INTERFACES_INIT_H diff --git a/src/interfaces/ipc.h b/src/interfaces/ipc.h new file mode 100644 index 0000000000..e9e6c78053 --- /dev/null +++ b/src/interfaces/ipc.h @@ -0,0 +1,71 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_INTERFACES_IPC_H +#define BITCOIN_INTERFACES_IPC_H + +#include <functional> +#include <memory> +#include <typeindex> + +namespace interfaces { +class Init; + +//! Interface providing access to interprocess-communication (IPC) +//! functionality. The IPC implementation is responsible for establishing +//! connections between a controlling process and a process being controlled. +//! When a connection is established, the process being controlled returns an +//! interfaces::Init pointer to the controlling process, which the controlling +//! process can use to get access to other interfaces and functionality. +//! +//! When spawning a new process, the steps are: +//! +//! 1. The controlling process calls interfaces::Ipc::spawnProcess(), which +//! calls ipc::Process::spawn(), which spawns a new process and returns a +//! socketpair file descriptor for communicating with it. +//! interfaces::Ipc::spawnProcess() then calls ipc::Protocol::connect() +//! passing the socketpair descriptor, which returns a local proxy +//! interfaces::Init implementation calling remote interfaces::Init methods. +//! 2. The spawned process calls interfaces::Ipc::startSpawnProcess(), which +//! calls ipc::Process::checkSpawned() to read command line arguments and +//! determine whether it is a spawned process and what socketpair file +//! descriptor it should use. It then calls ipc::Protocol::serve() to handle +//! incoming requests from the socketpair and invoke interfaces::Init +//! interface methods, and exit when the socket is closed. +//! 3. The controlling process calls local proxy interfaces::Init object methods +//! to make other proxy objects calling other remote interfaces. It can also +//! destroy the initial interfaces::Init object to close the connection and +//! shut down the spawned process. +class Ipc +{ +public: + virtual ~Ipc() = default; + + //! Spawn a child process returning pointer to its Init interface. + virtual std::unique_ptr<Init> spawnProcess(const char* exe_name) = 0; + + //! If this is a spawned process, block and handle requests from the parent + //! process by forwarding them to this process's Init interface, then return + //! true. If this is not a spawned child process, return false. + virtual bool startSpawnedProcess(int argc, char* argv[], int& exit_status) = 0; + + //! Add cleanup callback to remote interface that will run when the + //! interface is deleted. + template<typename Interface> + void addCleanup(Interface& iface, std::function<void()> cleanup) + { + addCleanup(typeid(Interface), &iface, std::move(cleanup)); + } + +protected: + //! Internal implementation of public addCleanup method (above) as a + //! type-erased virtual function, since template functions can't be virtual. + virtual void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) = 0; +}; + +//! Return implementation of Ipc interface. +std::unique_ptr<Ipc> MakeIpc(const char* exe_name, const char* process_argv0, Init& init); +} // namespace interfaces + +#endif // BITCOIN_INTERFACES_IPC_H |