1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
// 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 <winsock2.h>
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
|