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) 2021-present 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#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 <tinyformat.h>13#include <util/fs.h>14#include <util/log.h>16#include <csignal>17#include <cstdio>18#include <cstdlib>19#include <cstring>20#include <functional>21#include <memory>22#include <stdexcept>23#include <string>24#include <utility>25#include <vector>27#ifndef WIN3228#include <unistd.h>29#endif31namespace ipc {32namespace {33#ifndef WIN3234std::string g_ignore_ctrl_c;36void HandleCtrlC(int)37{38// (void)! needed to suppress -Wunused-result warning from GCC39(void)!write(STDOUT_FILENO, g_ignore_ctrl_c.data(), g_ignore_ctrl_c.size());40}41#endif43void IgnoreCtrlC(std::string message)44{45#ifndef WIN3246g_ignore_ctrl_c = std::move(message);47struct sigaction sa{};48sa.sa_handler = HandleCtrlC;49sigemptyset(&sa.sa_mask);50sa.sa_flags = SA_RESTART;51sigaction(SIGINT, &sa, nullptr);52#endif53}55class IpcImpl : public interfaces::Ipc56{57public:58IpcImpl(const char* exe_name, const char* process_argv0, interfaces::Init& init)59: m_exe_name(exe_name), m_process_argv0(process_argv0), m_init(init),60m_protocol(ipc::capnp::MakeCapnpProtocol(exe_name)), m_process(ipc::MakeProcess())61{62}63std::unique_ptr<interfaces::Init> spawnProcess(const char* new_exe_name) override64{65const auto [pid, socket] = m_process->spawn(new_exe_name, m_process_argv0);66LogDebug(::BCLog::IPC, "Process %s pid %i launched\n", new_exe_name, pid);67auto init = m_protocol->connect(m_protocol->makeStream(socket));68Ipc::addCleanup(*init, [this, new_exe_name, pid] {69int status = m_process->waitSpawned(pid);70LogDebug(::BCLog::IPC, "Process %s pid %i exited with status %i\n", new_exe_name, pid, status);71});72return init;73}74bool startSpawnedProcess(int argc, char* argv[], int& exit_status) override75{76exit_status = EXIT_FAILURE;77mp::SocketId socket{mp::SocketError};78if (!m_process->checkSpawned(argc, argv, socket)) {79return false;80}81IgnoreCtrlC(strprintf("[%s] SIGINT received — waiting for parent to shut down.\n", m_exe_name));82m_protocol->serve(m_init, [&] { return m_protocol->makeStream(socket); } );83exit_status = EXIT_SUCCESS;84return true;85}86std::unique_ptr<interfaces::Init> connectAddress(std::string& address) override87{88if (address.empty() || address == "0") return nullptr;89mp::SocketId fd;90if (address == "auto") {91// Treat "auto" the same as "unix" except don't treat it an as error92// if the connection is not accepted. Just return null so the caller93// can work offline without a connection, or spawn a new94// bitcoin-node process and connect to it.95address = "unix";96try {97fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);98} catch (const std::system_error& e) {99// If connection type is auto and socket path isn't accepting connections, or doesn't exist, catch the error and return null;100if (e.code() == std::errc::connection_refused || e.code() == std::errc::no_such_file_or_directory || e.code() == std::errc::not_a_directory) {101return nullptr;102}103throw;104} catch (const std::invalid_argument&) {105// Catch 'Unix address path "..." exceeded maximum socket path length' error106return nullptr;107}108} else {109fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);110}111return m_protocol->connect(m_protocol->makeStream(fd));112}113void listenAddress(std::string& address) override114{115mp::SocketId fd = m_process->bind(gArgs.GetDataDirNet(), m_exe_name, address);116m_protocol->listen(fd, m_init);117}118void disconnectIncoming() override119{120m_protocol->disconnectIncoming();121}122void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override123{124m_protocol->addCleanup(type, iface, std::move(cleanup));125}126Context& context() override { return m_protocol->context(); }127const char* m_exe_name;128const char* m_process_argv0;129interfaces::Init& m_init;130std::unique_ptr<Protocol> m_protocol;131std::unique_ptr<Process> m_process;132};133} // namespace134} // namespace ipc136namespace interfaces {137std::unique_ptr<Ipc> MakeIpc(const char* exe_name, const char* process_argv0, Init& init)138{139return std::make_unique<ipc::IpcImpl>(exe_name, process_argv0, init);140}141} // namespace interfaces
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.