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:
commit
2178d6a70c
121 changed files with 12644 additions and 0 deletions
72
include/naut/peer.h
Normal file
72
include/naut/peer.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* peer.h — BitTorrent peer wire protocol (BEP-3), sans-IO.
|
||||
*
|
||||
* This is a pure codec: it never touches a socket. You feed it bytes and it
|
||||
* yields parsed messages; you ask it to build a message and it writes bytes.
|
||||
* That keeps the protocol unit-testable in isolation and lets the SAME codec be
|
||||
* driven by the simple blocking leecher (Phase 3) and by the io_uring reactor
|
||||
* (Phase 6) without change — the I/O strategy is somebody else's problem.
|
||||
*/
|
||||
#ifndef NAUT_PEER_H
|
||||
#define NAUT_PEER_H
|
||||
|
||||
#include "naut/common.h"
|
||||
|
||||
#define NAUT_HANDSHAKE_LEN 68
|
||||
#define NAUT_PEERID_LEN 20
|
||||
/* Reject absurd length prefixes early: largest legitimate message is a PIECE,
|
||||
* 9 + block. Allow generous slack over the 16 KiB default block. */
|
||||
#define NAUT_MSG_MAX (1u << 20)
|
||||
|
||||
typedef enum {
|
||||
NAUT_MSG_CHOKE = 0,
|
||||
NAUT_MSG_UNCHOKE = 1,
|
||||
NAUT_MSG_INTERESTED = 2,
|
||||
NAUT_MSG_NOT_INTERESTED = 3,
|
||||
NAUT_MSG_HAVE = 4,
|
||||
NAUT_MSG_BITFIELD = 5,
|
||||
NAUT_MSG_REQUEST = 6,
|
||||
NAUT_MSG_PIECE = 7,
|
||||
NAUT_MSG_CANCEL = 8,
|
||||
NAUT_MSG_PORT = 9,
|
||||
NAUT_MSG_EXTENDED = 20, /* BEP-10 extension payload */
|
||||
NAUT_MSG_KEEPALIVE = 255, /* synthetic: length-prefix of 0 */
|
||||
} naut_msg_type;
|
||||
|
||||
typedef struct {
|
||||
naut_msg_type type;
|
||||
uint32_t index; /* HAVE/REQUEST/PIECE/CANCEL */
|
||||
uint32_t begin; /* REQUEST/PIECE/CANCEL */
|
||||
uint32_t length; /* REQUEST/CANCEL; PIECE: block length */
|
||||
const uint8_t *payload; /* PIECE: block bytes; BITFIELD: bytes */
|
||||
size_t payload_len;
|
||||
} naut_msg;
|
||||
|
||||
/* --- handshake ----------------------------------------------------------- */
|
||||
void naut_peer_handshake_build(uint8_t out[NAUT_HANDSHAKE_LEN],
|
||||
const uint8_t infohash[20],
|
||||
const uint8_t peerid[NAUT_PEERID_LEN],
|
||||
uint64_t reserved);
|
||||
/* Returns true on a well-formed handshake with the expected protocol string. */
|
||||
bool naut_peer_handshake_parse(const uint8_t in[NAUT_HANDSHAKE_LEN],
|
||||
uint8_t infohash[20],
|
||||
uint8_t peerid[NAUT_PEERID_LEN],
|
||||
uint64_t *reserved);
|
||||
|
||||
/* --- decode -------------------------------------------------------------- */
|
||||
/* Parse one message from buf[0..len). Returns bytes consumed (>0) with *out
|
||||
* filled (payload pointers alias into buf), 0 if more bytes are needed, or
|
||||
* NAUT_ERR_PROTO (<0) on a malformed/oversized frame. */
|
||||
int naut_peer_msg_parse(const uint8_t *buf, size_t len, naut_msg *out);
|
||||
|
||||
/* --- encode (all return bytes written) ----------------------------------- */
|
||||
size_t naut_peer_keepalive(uint8_t out[4]);
|
||||
size_t naut_peer_msg_simple(uint8_t out[5], naut_msg_type t); /* choke..not_interested */
|
||||
size_t naut_peer_msg_have(uint8_t out[9], uint32_t index);
|
||||
size_t naut_peer_msg_request(uint8_t out[17], uint32_t index, uint32_t begin, uint32_t length);
|
||||
size_t naut_peer_msg_cancel(uint8_t out[17], uint32_t index, uint32_t begin, uint32_t length);
|
||||
/* PIECE header (13 bytes); the block bytes follow separately on the wire. */
|
||||
size_t naut_peer_msg_piece_header(uint8_t out[13], uint32_t index, uint32_t begin, uint32_t block_len);
|
||||
/* BITFIELD into out (must hold 5 + nbytes); returns total length. */
|
||||
size_t naut_peer_msg_bitfield(uint8_t *out, const uint8_t *bf, size_t nbytes);
|
||||
|
||||
#endif /* NAUT_PEER_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue