Naut/include/naut/mse.h
ookami125 2178d6a70c 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>
2026-06-15 12:12:00 -04:00

88 lines
3.5 KiB
C

/* mse.h - BitTorrent Message Stream Encryption (MSE/PE) transport. */
#ifndef NAUT_MSE_H
#define NAUT_MSE_H
#include "naut/common.h"
#include "naut/peer.h"
#include "naut/rc4.h"
#include <sys/types.h>
#define NAUT_MSE_DH_LEN 96
typedef struct {
naut_rc4 send;
naut_rc4 recv;
bool active;
} naut_mse_stream;
/* ---- sans-IO handshake state machine ------------------------------------- *
* The outgoing MSE/PE handshake as a pure state machine over byte buffers — no
* sockets — so the same logic drives the blocking apps and the io_uring reactor
* (where blocking in a handshake would stall a whole core's worth of peers).
*
* Drive it like a codec: pump NEED_WRITE bytes out, feed NEED_READ bytes in,
* repeat until DONE or ERROR, then call _finish().
*
* h = naut_mse_handshake_begin(info_hash, peer_id, reserved);
* for (;;) switch (naut_mse_handshake_status(h)) {
* case NAUT_MSE_HS_NEED_WRITE: pull bytes, write them to the peer; break;
* case NAUT_MSE_HS_NEED_READ: read bytes from the peer, feed them; break;
* case NAUT_MSE_HS_DONE: naut_mse_handshake_finish(h, ...); goto ok;
* case NAUT_MSE_HS_ERROR: ... ; goto err;
* }
*/
typedef enum {
NAUT_MSE_HS_NEED_READ,
NAUT_MSE_HS_NEED_WRITE,
NAUT_MSE_HS_DONE,
NAUT_MSE_HS_ERROR,
} naut_mse_hs_status;
typedef struct naut_mse_handshake naut_mse_handshake;
naut_mse_handshake *naut_mse_handshake_begin(
const uint8_t info_hash[20],
const uint8_t peer_id[NAUT_PEERID_LEN],
uint64_t reserved);
void naut_mse_handshake_free(naut_mse_handshake *h);
naut_mse_hs_status naut_mse_handshake_status(const naut_mse_handshake *h);
/* Copy pending outgoing bytes into buf (up to cap); returns the count, 0 when
* nothing is queued. Call repeatedly until it returns 0. */
size_t naut_mse_handshake_pull(naut_mse_handshake *h, uint8_t *buf, size_t cap);
/* Feed received bytes; *consumed reports how many were absorbed (the rest, if
* any, must be re-fed — after DONE that remainder is the start of the encrypted
* payload stream). Returns the new status. */
naut_mse_hs_status naut_mse_handshake_feed(naut_mse_handshake *h,
const uint8_t *data, size_t len,
size_t *consumed);
/* Valid once status is DONE: hand out the negotiated stream and the peer's
* decrypted BitTorrent handshake. */
naut_err naut_mse_handshake_finish(naut_mse_handshake *h,
naut_mse_stream *stream,
uint8_t remote_handshake[NAUT_HANDSHAKE_LEN]);
/* Blocking convenience wrapper over the state machine: perform the whole
* outgoing handshake on a blocking socket, offering RC4 only. The BitTorrent
* handshake is carried as IA; the peer's decrypted handshake is returned in
* remote_handshake. */
naut_err naut_mse_client_handshake(
int fd,
const uint8_t info_hash[20],
const uint8_t peer_id[NAUT_PEERID_LEN],
uint64_t reserved,
naut_mse_stream *stream,
uint8_t remote_handshake[NAUT_HANDSHAKE_LEN]);
/* Stream I/O after a successful handshake. Encryption/decryption is in-place
* with connection-owned RC4 state. send_all preserves the caller's buffer. */
bool naut_mse_send_all(int fd, naut_mse_stream *stream,
const void *data, size_t len);
ssize_t naut_mse_recv(int fd, naut_mse_stream *stream,
void *data, size_t len);
#endif /* NAUT_MSE_H */