Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef MP_PROXY_H6#define MP_PROXY_H8#include <mp/util.h>10#include <cassert>11#include <functional>12#include <list>13#include <memory>14#include <stddef.h>15#include <tuple>16#include <type_traits>17#include <utility>18#include <variant> // IWYU pragma: keep20namespace mp {21class Connection;22class EventLoop;23//! Mapping from capnp interface type to proxy client implementation (specializations are generated by24//! proxy-codegen.cpp).25template <typename Interface> struct ProxyClient; // IWYU pragma: export26//! Mapping from capnp interface type to proxy server implementation (specializations are generated by27//! proxy-codegen.cpp).28template <typename Interface> struct ProxyServer; // IWYU pragma: export29//! Mapping from capnp method params type to method traits (specializations are generated by proxy-codegen.cpp).30template <typename Params> struct ProxyMethod; // IWYU pragma: export31//! Mapping from capnp struct type to struct traits (specializations are generated by proxy-codegen.cpp).32template <typename Struct> struct ProxyStruct; // IWYU pragma: export33//! Mapping from local c++ type to capnp type and traits (specializations are generated by proxy-codegen.cpp).34template <typename Type> struct ProxyType; // IWYU pragma: export36using CleanupList = std::list<std::function<void()>>;37using CleanupIt = typename CleanupList::iterator;39inline void CleanupRun(CleanupList& fns) {40while (!fns.empty()) {41auto fn = std::move(fns.front());42fns.pop_front();43fn();44}45}47//! Event loop smart pointer automatically managing m_num_refs.48//! If a lock pointer argument is passed, the specified lock will be used,49//! otherwise EventLoop::m_mutex will be locked when needed.50class EventLoopRef51{52public:53explicit EventLoopRef(EventLoop& loop, Lock* lock = nullptr);54EventLoopRef(EventLoopRef&& other) noexcept : m_loop(other.m_loop) { other.m_loop = nullptr; }55EventLoopRef(const EventLoopRef&) = delete;56EventLoopRef& operator=(const EventLoopRef&) = delete;57EventLoopRef& operator=(EventLoopRef&&) = delete;58~EventLoopRef() { reset(); }59EventLoop& operator*() const { assert(m_loop); return *m_loop; }60EventLoop* operator->() const { assert(m_loop); return m_loop; }61void reset(bool relock=false);63EventLoop* m_loop{nullptr};64Lock* m_lock{nullptr};65};67//! Context data associated with proxy client and server classes.68struct ProxyContext69{70Connection* connection;71EventLoopRef loop;72CleanupList cleanup_fns;74ProxyContext(Connection* connection);75};77//! Base class for generated ProxyClient classes that implement a C++ interface78//! and forward calls to a capnp interface.79template <typename Interface_, typename Impl_>80class ProxyClientBase : public Impl_81{82public:83using Interface = Interface_;84using Impl = Impl_;85using Sub = ProxyClient<Interface>;86using Super = ProxyClientBase<Interface, Impl>;88//! Construct libmultiprocess client object wrapping Cap'n Proto client89//! object with a reference to the associated mp::Connection object.90//!91//! The destroy_connection option determines whether destroying this client92//! object closes the connection. It is set to true for the93//! ProxyClient<InitInterface> object returned by ConnectStream, to let IPC94//! clients close the connection by freeing the object. It is false for95//! other client objects so they can be destroyed without affecting the96//! connection.97ProxyClientBase(typename Interface::Client client, Connection* connection, bool destroy_connection);98~ProxyClientBase() noexcept;100// construct/destroy methods called during client construction/destruction101// that can optionally be defined in capnp interfaces to invoke code on the102// server when proxy client objects are created and destroyed.103//104// The construct() method is not generally very useful, but can be used to105// run custom code on the server automatically when a ProxyClient client is106// constructed. The only current use is adding a construct method to Init107// interfaces that is called automatically on construction, so client and108// server exchange ThreadMap references and set Connection::m_thread_map109// values as soon as the Init client is created.110//111// construct @0 (threadMap: Proxy.ThreadMap) -> (threadMap: Proxy.ThreadMap);112//113// But construct() is not necessary for this, thread maps could be passed114// through a normal method that is just called explicitly rather than115// implicitly.116//117// The destroy() method is more generally useful than construct(), because118// it ensures that the server object will be destroyed synchronously before119// the client destructor returns, instead of asynchronously at some120// unpredictable time after the client object is already destroyed and121// client code has moved on. If the destroy method accepts a Context122// parameter like:123//124// destroy @0 (context: Proxy.Context) -> ();125//126// then it will also ensure that the destructor runs on the same thread the127// client used to make other RPC calls, instead of running on the server128// EventLoop thread and possibly blocking it.129static void construct(Super&) {}130static void destroy(Super&) {}132typename Interface::Client m_client;133ProxyContext m_context;134};136//! Customizable (through template specialization) base class used in generated ProxyClient implementations from137//! proxy-codegen.cpp.138template <typename Interface, typename Impl>139class ProxyClientCustom : public ProxyClientBase<Interface, Impl>140{141using ProxyClientBase<Interface, Impl>::ProxyClientBase;142};144//! Base class for generated ProxyServer classes that implement capnp server145//! methods and forward calls to a wrapped c++ implementation class.146template <typename Interface_, typename Impl_>147struct ProxyServerBase : public virtual Interface_::Server148{149public:150using Interface = Interface_;151using Impl = Impl_;153ProxyServerBase(std::shared_ptr<Impl> impl, Connection& connection);154virtual ~ProxyServerBase();155void invokeDestroy();156using Interface_::Server::thisCap;158/**159* Implementation pointer that may or may not be owned and deleted when this160* capnp server goes out of scope. It is owned for servers created to wrap161* unique_ptr<Impl> method arguments, but unowned for servers created to162* wrap Impl& method arguments.163*164* In the case of Impl& arguments, custom code is required on other side of165* the connection to delete the capnp client & server objects since native166* code on that side of the connection will just be taking a plain reference167* rather than a pointer, so won't be able to do its own cleanup. Right now168* this is implemented with addCloseHook callbacks to delete clients at169* appropriate times depending on semantics of the particular method being170* wrapped. */171std::shared_ptr<Impl> m_impl;172ProxyContext m_context;173};175//! Customizable (through template specialization) base class which ProxyServer176//! classes produced by generated code will inherit from. The default177//! specialization of this class just inherits from ProxyServerBase, but custom178//! specializations can be defined to control ProxyServer behavior.179//!180//! Specifically, it can be useful to specialize this class to add additional181//! state to ProxyServer classes, for example to cache state between IPC calls.182//! If this is done, however, care should be taken to ensure that the extra183//! state can be destroyed without blocking, because ProxyServer destructors are184//! called from the EventLoop thread, and if they block, it could deadlock the185//! program. One way to do avoid blocking is to clean up the state by pushing186//! cleanup callbacks to the m_context.cleanup_fns list, which run after the server187//! m_impl object is destroyed on the same thread destroying it (which will188//! either be an IPC worker thread if the ProxyServer is being explicitly189//! destroyed by a client calling a destroy() method with a Context argument and190//! Context.thread value set, or the temporary EventLoop::m_async_thread used to191//! run destructors without blocking the event loop when no-longer used server192//! objects are garbage collected by Cap'n Proto.) Alternately, if cleanup needs193//! to run before m_impl is destroyed, the specialization can override194//! invokeDestroy and destructor methods to do that.195template <typename Interface, typename Impl>196struct ProxyServerCustom : public ProxyServerBase<Interface, Impl>197{198using ProxyServerBase<Interface, Impl>::ProxyServerBase;199};201//! Function traits class used to get method parameter and result types, used in202//! generated ProxyClient and ProxyServer classes produced by gen.cpp to get C++203//! method type information. The generated code accesses these traits via204//! intermediate ProxyClientMethodTraits and ProxyServerMethodTraits classes,205//! which it is possible to specialize to change the way method arguments and206//! return values are handled.207//!208//! Fields of the trait class are:209//!210//! Params - TypeList of C++ ClassName::methodName parameter types211//! Result - Return type of ClassName::method212//! Param<N> - helper to access individual parameter types by index number.213//! Fwd<N> - helper to forward arguments by index number.214//! Fields - helper alias that appends Result type to the Params typelist if215//! it not void.216template <class Fn>217struct FunctionTraits;219//! Specialization of above extracting result and params types assuming the220//! template argument is a pointer-to-method type,221//! decltype(&ClassName::methodName)222template <class _Class, class _Result, class... _Params>223struct FunctionTraits<_Result (_Class::*const)(_Params...)>224{225using Params = TypeList<_Params...>;226using Result = _Result;227template <size_t N>228using Param = typename std::tuple_element<N, std::tuple<_Params...>>::type;229using Fields =230std::conditional_t<std::is_same_v<void, Result>, Params, TypeList<_Params..., _Result>>;232//! Enable perfect forwarding for clientInvoke calls. If parameter is a233//! value type or rvalue reference type, pass it as an rvalue-reference to234//! MakeClientParam and BuildField calls so it can be moved from, and if it235//! is an lvalue reference, pass it an lvalue reference so it won't be moved236//! from. This method does the same thing as std::forward except it takes a237//! parameter number instead of a type as a template argument, so generated238//! code calling this can be less repetitive and verbose.239template <size_t N>240static decltype(auto) Fwd(Param<N>& arg) { return static_cast<Param<N>&&>(arg); }241};243//! Traits class for a proxy method, providing the same244//! Params/Result/Param/Fields described in the FunctionTraits class above, plus245//! an additional invoke() method that calls the C++ method which is being246//! proxied, forwarding any arguments.247//!248//! The template argument should be the InterfaceName::MethodNameParams class249//! (generated by Cap'n Proto) associated with the method.250//!
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.