// Copyright (c) 2026 Bitflash developers // Distributed under the MIT/X11 software license. // // Transparent anonymous tunnel. Gives the existing CNode a plain local socket // while, behind it, a pair of pump threads bridge plaintext <-> echan <-> // rendezvous. CNode reads/writes normally and never knows its bytes travel // end-to-end encrypted through a meeting node (the Itzal `wrap()` pattern). // // Client side: resolve a `.btf` -> meeting node + service enc key (done by the // caller), then BtfClientTunnel connects through the relay, runs the echan // handshake, and returns a local SOCKET to hand a new outbound CNode. // // Service side: RvServiceRegister only registers -- callers must then block in // RvServiceWaitPaired until a client is actually paired to them. BtfServiceWrap // completes the echan handshake on that paired socket and returns a local // SOCKET for an inbound CNode. Wrapping a registered-but-unpaired socket reads // the relay's 0x01 pairing byte as the first byte of the client's ephemeral // key, which silently corrupts the tunnel instead of failing. #ifndef BITFLASH_BTFTUNNEL_H #define BITFLASH_BTFTUNNEL_H #include "btfrv.h" #ifdef _WIN32 #include typedef SOCKET btf_socket_t; #else typedef int btf_socket_t; #define INVALID_SOCKET (-1) #endif namespace btf { // Initialize (sockets + libsodium). Idempotent. bool TunnelInit(); // Which stage of BtfClientTunnel failed. INVALID_SOCKET alone says only "no // tunnel"; a caller that then guesses at causes in its log line sends whoever // reads it to the wrong component (issue #17: "relay unreachable or pool not // listening" blamed two healthy parts). The stage is what this side actually // knows -- report that. enum TunnelFail { TUNNEL_FAIL_NONE = 0, TUNNEL_FAIL_INIT, // local socket/crypto init failed TUNNEL_FAIL_DIAL, // TCP connect to the meeting node failed TUNNEL_FAIL_REFUSED, // relay reachable, but no service registered under the pubkey TUNNEL_FAIL_PAIR, // relay connection died before pairing completed TUNNEL_FAIL_HANDSHAKE, // end-to-end channel handshake failed TUNNEL_FAIL_LOCAL, // local pump plumbing (socket pair / threads) failed }; // Short description of a TunnelFail for log lines. const char* TunnelFailText(TunnelFail f); // Client: dial the service registered under `target_pubkey` at the meeting node // (host:port), box to its static x25519 `service_enc_pub`, and return a local // plaintext SOCKET tunneled end-to-end to the service. INVALID_SOCKET on error // -- with `pFail`, if given, naming the stage that failed. btf_socket_t BtfClientTunnel(const char* meeting_host, unsigned short port, const unsigned char target_pubkey[32], const unsigned char service_enc_pub[32], TunnelFail* pFail = 0); // Service: wrap an already-paired rendezvous socket (RvServiceRegister followed // by RvServiceWaitPaired -- the pairing byte MUST already be consumed) with // echan using my static x25519 secret, returning a local plaintext SOCKET // for an inbound CNode. Consumes `rv` (closed when the tunnel tears down). btf_socket_t BtfServiceWrap(RvSocket rv, const unsigned char my_enc_sk[32]); } // namespace btf #endif