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 <ipc/process.h>6#include <ipc/protocol.h>7#include <mp/util.h>8#include <tinyformat.h>9#include <util/fs.h>10#include <util/log.h>11#include <util/strencodings.h>12#include <util/syserror.h>14#include <cstdint>15#include <cstdlib>16#include <cstring>17#include <cerrno>18#include <exception>19#include <iostream>20#include <stdexcept>21#include <utility>22#include <vector>24#include <sys/socket.h>25#include <sys/un.h>26#include <unistd.h>28using util::RemovePrefixView;30namespace ipc {31namespace {32class ProcessImpl : public Process33{34public:35std::tuple<mp::ProcessId, mp::SocketId> spawn(const std::string& new_exe_name, const fs::path& argv0_path) override36{37return mp::SpawnProcess([&](std::string connect_info) {38fs::path path = argv0_path;39path.remove_filename();40path /= fs::PathFromString(new_exe_name);41return std::vector<std::string>{fs::PathToString(path), "-ipcfd", std::move(connect_info)};42});43}44int waitSpawned(mp::ProcessId pid) override { return mp::WaitProcess(pid); }45bool checkSpawned(int argc, char* argv[], mp::SocketId& socket) override46{47// If this process was not started with a single -ipcfd argument, it is48// not a process spawned by the spawn() call above, so return false and49// do not try to serve requests.50if (argc != 3 || strcmp(argv[1], "-ipcfd") != 0) {51return false;52}53// If a single -ipcfd argument was provided, return true and get the54// file descriptor so Protocol::serve() can be called to handle55// requests from the parent process. The -ipcfd argument is not valid56// in combination with other arguments because the parent process57// should be able to control the child process through the IPC protocol58// without passing information out of band.59try {60socket = mp::StartSpawned(argv[2]);61} catch (const std::exception& e) {62throw std::runtime_error(strprintf("Invalid -ipcfd number '%s' (%s)", argv[2], e.what()));63}64return true;65}66mp::SocketId connect(const fs::path& data_dir,67const std::string& dest_exe_name,68std::string& address) override;69mp::SocketId bind(const fs::path& data_dir, const std::string& exe_name, std::string& address) override;70};72static bool ParseAddress(std::string& address,73const fs::path& data_dir,74const std::string& dest_exe_name,75struct sockaddr_un& addr,76std::string& error)77{78if (address == "unix" || address.starts_with("unix:")) {79fs::path path;80if (address.size() <= 5) {81path = data_dir / fs::PathFromString(strprintf("%s.sock", RemovePrefixView(dest_exe_name, "bitcoin-")));82} else {83path = data_dir / fs::PathFromString(address.substr(5));84}85std::string path_str = fs::PathToString(path);86address = strprintf("unix:%s", path_str);87if (path_str.size() >= sizeof(addr.sun_path)) {88error = strprintf("Unix address path %s exceeded maximum socket path length", fs::quoted(fs::PathToString(path)));89return false;90}91memset(&addr, 0, sizeof(addr));92addr.sun_family = AF_UNIX;93strncpy(addr.sun_path, path_str.c_str(), sizeof(addr.sun_path)-1);94return true;95}97error = strprintf("Unrecognized address '%s'", address);98return false;99}101mp::SocketId ProcessImpl::connect(const fs::path& data_dir,102const std::string& dest_exe_name,103std::string& address)104{105struct sockaddr_un addr;106std::string error;107if (!ParseAddress(address, data_dir, dest_exe_name, addr, error)) {108throw std::invalid_argument(error);109}111mp::SocketId fd;112if ((fd = ::socket(addr.sun_family, SOCK_STREAM, 0)) == mp::SocketError) {113throw std::system_error(errno, std::system_category());114}115if (::connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {116return fd;117}118int connect_error = errno;119if (::close(fd) != 0) {120LogWarning("Error closing file descriptor %i '%s': %s", fd, address, SysErrorString(errno));121}122throw std::system_error(connect_error, std::system_category());123}125mp::SocketId ProcessImpl::bind(const fs::path& data_dir, const std::string& exe_name, std::string& address)126{127struct sockaddr_un addr;128std::string error;129if (!ParseAddress(address, data_dir, exe_name, addr, error)) {130throw std::invalid_argument(error);131}133if (addr.sun_family == AF_UNIX) {134fs::path path = addr.sun_path;135if (path.has_parent_path()) fs::create_directories(path.parent_path());136if (fs::symlink_status(path).type() == fs::file_type::socket) {137fs::remove(path);138}139}141mp::SocketId fd;142if ((fd = ::socket(addr.sun_family, SOCK_STREAM, 0)) == mp::SocketError) {143throw std::system_error(errno, std::system_category());144}146if (::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {147return fd;148}149int bind_error = errno;150if (::close(fd) != 0) {151LogWarning("Error closing file descriptor %i: %s", fd, SysErrorString(errno));152}153throw std::system_error(bind_error, std::system_category());154}155} // namespace157std::unique_ptr<Process> MakeProcess() { return std::make_unique<ProcessImpl>(); }158} // namespace ipc
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.