Bitcoin Core  29.1.0
P2P Digital Currency
interfaces.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021-2022 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 <common/args.h>
6 #include <common/system.h>
7 #include <interfaces/init.h>
8 #include <interfaces/ipc.h>
9 #include <ipc/capnp/protocol.h>
10 #include <ipc/process.h>
11 #include <ipc/protocol.h>
12 #include <logging.h>
13 #include <tinyformat.h>
14 #include <util/fs.h>
15 
16 #include <cstdio>
17 #include <cstdlib>
18 #include <functional>
19 #include <memory>
20 #include <stdexcept>
21 #include <string.h>
22 #include <string>
23 #include <unistd.h>
24 #include <utility>
25 #include <vector>
26 
27 namespace ipc {
28 namespace {
29 class IpcImpl : public interfaces::Ipc
30 {
31 public:
32  IpcImpl(const char* exe_name, const char* process_argv0, interfaces::Init& init)
33  : m_exe_name(exe_name), m_process_argv0(process_argv0), m_init(init),
34  m_protocol(ipc::capnp::MakeCapnpProtocol()), m_process(ipc::MakeProcess())
35  {
36  }
37  std::unique_ptr<interfaces::Init> spawnProcess(const char* new_exe_name) override
38  {
39  int pid;
40  int fd = m_process->spawn(new_exe_name, m_process_argv0, pid);
41  LogDebug(::BCLog::IPC, "Process %s pid %i launched\n", new_exe_name, pid);
42  auto init = m_protocol->connect(fd, m_exe_name);
43  Ipc::addCleanup(*init, [this, new_exe_name, pid] {
44  int status = m_process->waitSpawned(pid);
45  LogDebug(::BCLog::IPC, "Process %s pid %i exited with status %i\n", new_exe_name, pid, status);
46  });
47  return init;
48  }
49  bool startSpawnedProcess(int argc, char* argv[], int& exit_status) override
50  {
51  exit_status = EXIT_FAILURE;
52  int32_t fd = -1;
53  if (!m_process->checkSpawned(argc, argv, fd)) {
54  return false;
55  }
56  m_protocol->serve(fd, m_exe_name, m_init);
58  return true;
59  }
60  std::unique_ptr<interfaces::Init> connectAddress(std::string& address) override
61  {
62  if (address.empty() || address == "0") return nullptr;
63  int fd;
64  if (address == "auto") {
65  // Treat "auto" the same as "unix" except don't treat it an as error
66  // if the connection is not accepted. Just return null so the caller
67  // can work offline without a connection, or spawn a new
68  // bitcoin-node process and connect to it.
69  address = "unix";
70  try {
71  fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);
72  } catch (const std::system_error& e) {
73  // If connection type is auto and socket path isn't accepting connections, or doesn't exist, catch the error and return null;
74  if (e.code() == std::errc::connection_refused || e.code() == std::errc::no_such_file_or_directory) {
75  return nullptr;
76  }
77  throw;
78  }
79  } else {
80  fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);
81  }
82  return m_protocol->connect(fd, m_exe_name);
83  }
84  void listenAddress(std::string& address) override
85  {
86  int fd = m_process->bind(gArgs.GetDataDirNet(), m_exe_name, address);
87  m_protocol->listen(fd, m_exe_name, m_init);
88  }
89  void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override
90  {
91  m_protocol->addCleanup(type, iface, std::move(cleanup));
92  }
93  Context& context() override { return m_protocol->context(); }
94  const char* m_exe_name;
95  const char* m_process_argv0;
96  interfaces::Init& m_init;
97  std::unique_ptr<Protocol> m_protocol;
98  std::unique_ptr<Process> m_process;
99 };
100 } // namespace
101 } // namespace ipc
102 
103 namespace interfaces {
104 std::unique_ptr<Ipc> MakeIpc(const char* exe_name, const char* process_argv0, Init& init)
105 {
106  return std::make_unique<ipc::IpcImpl>(exe_name, process_argv0, init);
107 }
108 } // namespace interfaces
return EXIT_SUCCESS
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:234
std::unique_ptr< interfaces::Init > init
std::unique_ptr< Ipc > MakeIpc(const char *exe_name, const char *process_argv0, Init &init)
Return implementation of Ipc interface.
Definition: interfaces.cpp:104
Definition: ipc.h:12
std::unique_ptr< Protocol > MakeCapnpProtocol()
Definition: protocol.cpp:102
ArgsManager gArgs
Definition: args.cpp:42
#define LogDebug(category,...)
Definition: logging.h:381
int exit_status
Initial interface created when a process is first started, and used to give and get access to other i...
Definition: init.h:30
Interface providing access to interprocess-communication (IPC) functionality.
Definition: ipc.h:49
std::unique_ptr< Process > MakeProcess()
Constructor for Process interface.
Definition: process.cpp:154