Bitcoin Core  21.99.0
P2P Digital Currency
protocol.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <interfaces/init.h>
6 #include <ipc/capnp/init.capnp.h>
7 #include <ipc/capnp/init.capnp.proxy.h>
8 #include <ipc/capnp/protocol.h>
9 #include <ipc/exception.h>
10 #include <ipc/protocol.h>
11 #include <kj/async.h>
12 #include <logging.h>
13 #include <mp/proxy-io.h>
14 #include <mp/proxy-types.h>
15 #include <mp/util.h>
16 #include <util/threadnames.h>
17 
18 #include <assert.h>
19 #include <errno.h>
20 #include <future>
21 #include <memory>
22 #include <mutex>
23 #include <optional>
24 #include <string>
25 #include <thread>
26 
27 namespace ipc {
28 namespace capnp {
29 namespace {
30 void IpcLogFn(bool raise, std::string message)
31 {
32  LogPrint(BCLog::IPC, "%s\n", message);
33  if (raise) throw Exception(message);
34 }
35 
36 class CapnpProtocol : public Protocol
37 {
38 public:
39  ~CapnpProtocol() noexcept(true)
40  {
41  if (m_loop) {
42  std::unique_lock<std::mutex> lock(m_loop->m_mutex);
43  m_loop->removeClient(lock);
44  }
45  if (m_loop_thread.joinable()) m_loop_thread.join();
46  assert(!m_loop);
47  };
48  std::unique_ptr<interfaces::Init> connect(int fd, const char* exe_name) override
49  {
50  startLoop(exe_name);
51  return mp::ConnectStream<messages::Init>(*m_loop, fd);
52  }
53  void serve(int fd, const char* exe_name, interfaces::Init& init) override
54  {
55  assert(!m_loop);
56  mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
57  m_loop.emplace(exe_name, &IpcLogFn, nullptr);
58  mp::ServeStream<messages::Init>(*m_loop, fd, init);
59  m_loop->loop();
60  m_loop.reset();
61  }
62  void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override
63  {
64  mp::ProxyTypeRegister::types().at(type)(iface).cleanup.emplace_back(std::move(cleanup));
65  }
66  void startLoop(const char* exe_name)
67  {
68  if (m_loop) return;
69  std::promise<void> promise;
70  m_loop_thread = std::thread([&] {
71  util::ThreadRename("capnp-loop");
72  m_loop.emplace(exe_name, &IpcLogFn, nullptr);
73  {
74  std::unique_lock<std::mutex> lock(m_loop->m_mutex);
75  m_loop->addClient(lock);
76  }
77  promise.set_value();
78  m_loop->loop();
79  m_loop.reset();
80  });
81  promise.get_future().wait();
82  }
83  std::thread m_loop_thread;
84  std::optional<mp::EventLoop> m_loop;
85 };
86 } // namespace
87 
88 std::unique_ptr<Protocol> MakeCapnpProtocol() { return std::make_unique<CapnpProtocol>(); }
89 } // namespace capnp
90 } // namespace ipc
BCLog::IPC
@ IPC
Definition: logging.h:61
ipc
Definition: protocol.cpp:27
interfaces::Init
Initial interface created when a process is first started, and used to give and get access to other i...
Definition: init.h:26
ipc::Exception
Exception class thrown when a call to remote method fails due to an IPC error, like a socket getting ...
Definition: exception.h:13
util::ThreadRename
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:57
init.h
m_loop
std::optional< mp::EventLoop > m_loop
Definition: protocol.cpp:84
LogPrint
#define LogPrint(category,...)
Definition: logging.h:188
ipc::capnp::MakeCapnpProtocol
std::unique_ptr< Protocol > MakeCapnpProtocol()
Definition: protocol.cpp:88
protocol.h
init
Definition: bitcoin-node.cpp:12
logging.h
ipc::Protocol
IPC protocol interface for calling IPC methods over sockets.
Definition: protocol.h:19
exception.h
m_loop_thread
std::thread m_loop_thread
Definition: protocol.cpp:83
threadnames.h
assert
assert(std::addressof(::ChainstateActive().CoinsTip())==std::addressof(coins_cache))
protocol.h