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

114
tests/bench/bench_scale.c Normal file
View file

@ -0,0 +1,114 @@
/* Multicore hash/RC4 offload benchmark for the Phase 6 CPU budget. */
#include "naut/hash.h"
#include "naut/rc4.h"
#include "naut/worker.h"
#include <poll.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define JOB_BYTES (1u << 20)
#define JOB_COUNT 64
typedef enum { BENCH_SHA1, BENCH_SHA256, BENCH_RC4 } bench_kind;
typedef struct {
naut_job base;
bench_kind kind;
uint8_t *data;
uint8_t digest[NAUT_SHA256_LEN];
} bench_job;
static double now_seconds(void) {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return time.tv_sec + time.tv_nsec * 1e-9;
}
static void run_job(naut_job *base) {
bench_job *job = base->context;
if (job->kind == BENCH_SHA1) {
naut_sha1(job->data, JOB_BYTES, job->digest);
} else if (job->kind == BENCH_SHA256) {
naut_sha256(job->data, JOB_BYTES, job->digest);
} else {
static const uint8_t key[20] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
};
naut_rc4 rc4;
naut_rc4_init(&rc4, key, sizeof key, 1024);
naut_rc4_xor(&rc4, job->data, JOB_BYTES);
}
base->result = NAUT_OK;
}
static double run(naut_worker_pool *pool, bench_job *jobs,
bench_kind kind, int rounds) {
for (int i = 0; i < JOB_COUNT; i++) jobs[i].kind = kind;
int total_completed = 0;
double start = now_seconds();
for (int round = 0; round < rounds; round++) {
for (int i = 0; i < JOB_COUNT; i++) {
while (!naut_worker_submit(pool, &jobs[i].base))
sched_yield();
}
int completed = 0;
while (completed < JOB_COUNT) {
naut_job *base;
if (naut_worker_complete(pool, &base)) {
(void)base;
completed++;
total_completed++;
continue;
}
struct pollfd pfd = {
.fd = naut_worker_eventfd(pool),
.events = POLLIN,
};
if (poll(&pfd, 1, 5000) <= 0) break;
uint64_t count;
(void)read(pfd.fd, &count, sizeof count);
}
if (completed != JOB_COUNT) break;
}
double seconds = now_seconds() - start;
return ((double)total_completed * JOB_BYTES / 1e9) / seconds;
}
int main(int argc, char **argv) {
int threads = argc > 1 ? atoi(argv[1]) : 8;
int rounds = argc > 2 ? atoi(argv[2]) : 16;
if (threads < 1 || rounds < 1) return 2;
naut_worker_pool *pool =
naut_worker_pool_create((uint32_t)threads, 128, -1);
if (!pool) return 1;
bench_job *jobs = calloc(JOB_COUNT, sizeof(*jobs));
uint8_t *slab = aligned_alloc(NAUT_PAGE, JOB_COUNT * JOB_BYTES);
if (!jobs || !slab) return 1;
memset(slab, 0xa5, JOB_COUNT * JOB_BYTES);
for (int i = 0; i < JOB_COUNT; i++) {
jobs[i].base.run = run_job;
jobs[i].base.context = &jobs[i];
jobs[i].data = slab + (size_t)i * JOB_BYTES;
}
double sha1 = run(pool, jobs, BENCH_SHA1, rounds);
double sha256 = run(pool, jobs, BENCH_SHA256, rounds);
double rc4 = run(pool, jobs, BENCH_RC4, rounds);
printf("%d workers, %.2f GiB processed per primitive\n",
threads, (double)JOB_COUNT * rounds * JOB_BYTES / (1u << 30));
printf(" sha1 %.2f GB/s\n", sha1);
printf(" sha256 %.2f GB/s\n", sha256);
printf(" rc4 %.2f GB/s\n", rc4);
free(slab);
free(jobs);
naut_worker_pool_destroy(pool);
return 0;
}