Initial commit: Naut-Torrent — from-scratch 10 GbE BitTorrent client

A maintainable, extensible BitTorrent client (C11, Linux/io_uring) targeting
10 GbE saturation. All torrent functionality is built from scratch; liburing
is the only linked third-party dependency on the data path.

Implements Phases 1-7 of the roadmap:
- core: page-aligned buffer pool, MPMC/Treiber queues, bitfields, worker pool
- crypto: SHA-1/256 (SHA-NI + scalar), Merkle (BEP-52), RC4 (MSE)
- bencode/metainfo: zero-copy parser, v1/v2/hybrid .torrent + magnet
- peer: sans-IO wire codec, MSE/PE handshake state machine, BEP-10, ut_metadata, PEX
- piece/storage: block-level multi-peer engine, rarest-first + endgame,
  per-file completion events + single-file relocate (move-as-you-finish)
- tracker/dht: HTTP + UDP (BEP-15) trackers, BEP-5 KRPC iterative lookup
- platform: io_uring reactor (SQPOLL, registered buffers, SEND_ZC)
- surface: versioned RPC, native plugin ABI, sandboxed Lua scripting, nautd/nautctl

Verified against libtorrent (single/multi/hybrid, MSE, magnet-via-DHT, swarm);
unit + interop tests green; ASan/UBSan/TSan clean. Scripting reference in
docs/scripting.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ookami125 2026-06-15 12:12:00 -04:00
commit 2178d6a70c
121 changed files with 12644 additions and 0 deletions

72
src/crypto/sha1.c Normal file
View file

@ -0,0 +1,72 @@
#include "naut/hash.h"
#include <string.h>
static inline uint32_t rol(uint32_t x, int n) { return (x << n) | (x >> (32 - n)); }
static void sha1_block(uint32_t h[5], const uint8_t *p, size_t nblocks) {
for (size_t b = 0; b < nblocks; b++, p += 64) {
uint32_t w[80];
for (int i = 0; i < 16; i++)
w[i] = ((uint32_t)p[i*4] << 24) | ((uint32_t)p[i*4+1] << 16) |
((uint32_t)p[i*4+2] << 8) | (uint32_t)p[i*4+3];
for (int i = 16; i < 80; i++)
w[i] = rol(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1);
uint32_t a = h[0], bb = h[1], c = h[2], d = h[3], e = h[4];
for (int i = 0; i < 80; i++) {
uint32_t f, k;
if (i < 20) { f = (bb & c) | (~bb & d); k = 0x5A827999; }
else if (i < 40) { f = bb ^ c ^ d; k = 0x6ED9EBA1; }
else if (i < 60) { f = (bb & c) | (bb & d) | (c & d); k = 0x8F1BBCDC; }
else { f = bb ^ c ^ d; k = 0xCA62C1D6; }
uint32_t t = rol(a, 5) + f + e + k + w[i];
e = d; d = c; c = rol(bb, 30); bb = a; a = t;
}
h[0] += a; h[1] += bb; h[2] += c; h[3] += d; h[4] += e;
}
}
void naut_sha1_init(naut_sha1_ctx *c) {
c->h[0] = 0x67452301; c->h[1] = 0xEFCDAB89; c->h[2] = 0x98BADCFE;
c->h[3] = 0x10325476; c->h[4] = 0xC3D2E1F0;
c->len = 0; c->used = 0;
}
void naut_sha1_update(naut_sha1_ctx *c, const void *data, size_t len) {
const uint8_t *p = data;
c->len += len;
if (c->used) {
size_t need = 64 - c->used;
size_t take = len < need ? len : need;
memcpy(c->block + c->used, p, take);
c->used += take; p += take; len -= take;
if (c->used == 64) { sha1_block(c->h, c->block, 1); c->used = 0; }
}
if (len >= 64) {
size_t nb = len / 64;
sha1_block(c->h, p, nb);
p += nb * 64; len -= nb * 64;
}
if (len) { memcpy(c->block, p, len); c->used = len; }
}
void naut_sha1_final(naut_sha1_ctx *c, uint8_t out[NAUT_SHA1_LEN]) {
uint64_t bits = c->len * 8;
uint8_t pad = 0x80;
naut_sha1_update(c, &pad, 1);
uint8_t zero = 0;
while (c->used != 56) naut_sha1_update(c, &zero, 1);
uint8_t lenbe[8];
for (int i = 0; i < 8; i++) lenbe[i] = (uint8_t)(bits >> (56 - i*8));
naut_sha1_update(c, lenbe, 8);
for (int i = 0; i < 5; i++) {
out[i*4] = (uint8_t)(c->h[i] >> 24);
out[i*4+1] = (uint8_t)(c->h[i] >> 16);
out[i*4+2] = (uint8_t)(c->h[i] >> 8);
out[i*4+3] = (uint8_t)(c->h[i]);
}
}
void naut_sha1(const void *data, size_t len, uint8_t out[NAUT_SHA1_LEN]) {
naut_sha1_ctx c; naut_sha1_init(&c); naut_sha1_update(&c, data, len); naut_sha1_final(&c, out);
}