diff options
| author | Bitflash <btf01@proton.me> | 2026-08-01 13:10:23 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-01 13:10:23 -0300 |
| commit | 21c8bb63cb85f3001ddee9237b1d7e689675d293 (patch) | |
| tree | 9668f6bf39635424a6180c7a7edb6c7931ea7545 /src/btftunnel.cpp | |
| parent | 7131c30c33c980f0ba1d37dfc6a3fbe8c319813e (diff) | |
diag: count sockets by where they were created, and whether the close took (#86)
A node was found holding 1502 sockets in Windows bound state, one ephemeral port
each, 9% of the machine range in nineteen hours. Reading the code did not find
it: every connect() failure path here closes its socket.
So count. Every socket is tagged at creation and untagged at close, across all
ten sites, with a counter for closes that fail. Already rules out three
explanations: nothing is created or closed behind the counter (untagged closes
are zero), no close is failing, and the leaked sockets are not in the live set --
tracked live matches what the OS reports as established, while the bound pile is
something the program already closed successfully.
Diffstat (limited to 'src/btftunnel.cpp')
| -rw-r--r-- | src/btftunnel.cpp | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/src/btftunnel.cpp b/src/btftunnel.cpp index 65c4b89..63d178b 100644 --- a/src/btftunnel.cpp +++ b/src/btftunnel.cpp | |||
| @@ -23,6 +23,7 @@ typedef int SOCKET; | |||
| 23 | #define SD_BOTH SHUT_RDWR | 23 | #define SD_BOTH SHUT_RDWR |
| 24 | #endif | 24 | #endif |
| 25 | #endif | 25 | #endif |
| 26 | #include "sockcount.h" | ||
| 26 | #include <cstring> | 27 | #include <cstring> |
| 27 | #include <vector> | 28 | #include <vector> |
| 28 | #include <thread> | 29 | #include <thread> |
| @@ -39,7 +40,7 @@ bool TunnelInit() | |||
| 39 | // Returns app end and pump end; both are ordinary full-duplex TCP sockets. | 40 | // Returns app end and pump end; both are ordinary full-duplex TCP sockets. |
| 40 | static bool MakeLocalPair(btf_socket_t& appEnd, btf_socket_t& pumpEnd) | 41 | static bool MakeLocalPair(btf_socket_t& appEnd, btf_socket_t& pumpEnd) |
| 41 | { | 42 | { |
| 42 | SOCKET listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 43 | SOCKET listener = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), SOCK_PAIR_LISTEN); |
| 43 | if (listener == INVALID_SOCKET) return false; | 44 | if (listener == INVALID_SOCKET) return false; |
| 44 | 45 | ||
| 45 | struct sockaddr_in addr; | 46 | struct sockaddr_in addr; |
| @@ -47,23 +48,23 @@ static bool MakeLocalPair(btf_socket_t& appEnd, btf_socket_t& pumpEnd) | |||
| 47 | addr.sin_family = AF_INET; | 48 | addr.sin_family = AF_INET; |
| 48 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | 49 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 49 | addr.sin_port = 0; // ephemeral | 50 | addr.sin_port = 0; // ephemeral |
| 50 | if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) != 0) { closesocket(listener); return false; } | 51 | if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) != 0) { BtfCloseSocket(listener); return false; } |
| 51 | if (listen(listener, 1) != 0) { closesocket(listener); return false; } | 52 | if (listen(listener, 1) != 0) { BtfCloseSocket(listener); return false; } |
| 52 | 53 | ||
| 53 | #ifdef _WIN32 | 54 | #ifdef _WIN32 |
| 54 | int len = sizeof(addr); | 55 | int len = sizeof(addr); |
| 55 | #else | 56 | #else |
| 56 | socklen_t len = sizeof(addr); | 57 | socklen_t len = sizeof(addr); |
| 57 | #endif | 58 | #endif |
| 58 | if (getsockname(listener, (struct sockaddr*)&addr, &len) != 0) { closesocket(listener); return false; } | 59 | if (getsockname(listener, (struct sockaddr*)&addr, &len) != 0) { BtfCloseSocket(listener); return false; } |
| 59 | 60 | ||
| 60 | SOCKET a = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | 61 | SOCKET a = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), SOCK_PAIR_APP); |
| 61 | if (a == INVALID_SOCKET) { closesocket(listener); return false; } | 62 | if (a == INVALID_SOCKET) { BtfCloseSocket(listener); return false; } |
| 62 | if (connect(a, (struct sockaddr*)&addr, sizeof(addr)) != 0) { closesocket(a); closesocket(listener); return false; } | 63 | if (connect(a, (struct sockaddr*)&addr, sizeof(addr)) != 0) { BtfCloseSocket(a); BtfCloseSocket(listener); return false; } |
| 63 | 64 | ||
| 64 | SOCKET b = accept(listener, NULL, NULL); | 65 | SOCKET b = BtfSocketTag(accept(listener, NULL, NULL), SOCK_PAIR_PUMP); |
| 65 | closesocket(listener); | 66 | BtfCloseSocket(listener); |
| 66 | if (b == INVALID_SOCKET) { closesocket(a); return false; } | 67 | if (b == INVALID_SOCKET) { BtfCloseSocket(a); return false; } |
| 67 | 68 | ||
| 68 | appEnd = a; | 69 | appEnd = a; |
| 69 | pumpEnd = b; | 70 | pumpEnd = b; |
| @@ -129,7 +130,7 @@ static btf_socket_t StartTunnel(RvSocket rv, const unsigned char shared[32]) | |||
| 129 | std::thread(PumpOut, pumpEnd, rv, key).detach(); | 130 | std::thread(PumpOut, pumpEnd, rv, key).detach(); |
| 130 | std::thread([pumpEnd, rv, key]() { | 131 | std::thread([pumpEnd, rv, key]() { |
| 131 | PumpIn(pumpEnd, rv, key); | 132 | PumpIn(pumpEnd, rv, key); |
| 132 | closesocket(pumpEnd); | 133 | BtfCloseSocket(pumpEnd); |
| 133 | RvClose(rv); | 134 | RvClose(rv); |
| 134 | }).detach(); | 135 | }).detach(); |
| 135 | return appEnd; | 136 | return appEnd; |