WebSeed

class WebSeed(client: HttpClient, baseUrl: String, torrent: TorrentInfo)

A BEP-19 web seed (url-list, "GetRight" style): a plain HTTP(S) server that hosts the torrent's files so a client can download them with ordinary ranged GETs instead of the BitTorrent wire protocol.

Coroutine port of libtorrent's web_peer_connection (src/web_peer_connection.cpp) and its base web_connection_base (src/web_connection_base.cpp). libtorrent runs a web seed as a full pseudo-peer_connection: it fabricates a have-all bitfield, lets the normal piece picker schedule blocks, then in write_request turns each BitTorrent block request into one or more HTTP GET … Range: bytes=a-b requests, one per file the block overlaps, and re-assembles the response bytes back into the piece. This class keeps that request-mapping + fetch core and drops the peer-connection machinery (choke/interest, the receive-buffer state machine, redirect-following, pad-file zero-filling), which belong to the orchestrator above.

URL construction mirrors web_peer_connection's constructor and write_request:

  • Single-file torrent: the file is the torrent. libtorrent uses the seed URL as-is, except when the URL ends in / it appends the (already-encoded) torrent name (web_peer_connection.cpp:108-121). So here, baseUrl ending in /baseUrl + escapedName, otherwise baseUrl verbatim.

  • Multi-file torrent: the seed URL is a directory. libtorrent ensures a trailing slash (web_peer_connection.cpp:101-107) then appends each file's percent-encoded path (escape_file_path, web_peer_connection.cpp:497). So here, each URL is baseUrl(/) + escapePath(relativeFilePath).

Block → range mapping (rangesFor) reproduces file_storage::map_block (src/file_storage.cpp:485): the request's absolute torrent offset is piece * pieceLength + offset, and the run of length bytes is sliced at file boundaries, yielding one HttpRange per file touched. A block that straddles a file boundary therefore produces multiple ranges, fetched and concatenated in order. libtorrent does the same: it issues multiple GETs and joins the payloads.

Threading. fetchBlock/downloadPiece suspend on the injected client only; they hold no mutable state, so a single WebSeed may be shared across coroutines.

Parameters

client

the ktor HttpClient (engine chosen by the caller: CIO on JVM/Android, Darwin on iOS), injected so it can be mocked.

baseUrl

the web-seed URL from the torrent's url-list.

torrent

the parsed torrent whose files this seed serves.

Constructors

Link copied to clipboard
constructor(client: HttpClient, baseUrl: String, torrent: TorrentInfo)

Properties

Link copied to clipboard
val url: String

The seed URL, normalised once up-front the way libtorrent does in the web_peer_connection constructor: a trailing slash is ensured for the multi-file case (so file paths append cleanly), and for a single-file torrent a /-terminated URL gets the escaped torrent name appended.

Functions

Link copied to clipboard
suspend fun downloadPiece(piece: Int): ByteArray

Download an entire piece by fetching it as a single contiguous block (offset 0, the full TorrentInfo.storage piece size). The final piece is shorter than TorrentInfo.pieceLength; io.github.yuroyami.kitetorrent.torrent.FileStorage.pieceSize gives the exact length. Multi-file pieces still fan out to per-file ranges inside fetchBlock.

Link copied to clipboard
suspend fun fetchBlock(piece: Int, offset: Int, length: Int): ByteArray

Fetch one BitTorrent block (length bytes at (piece, offset)) from this web seed, issuing a ranged HTTP GET per file the block overlaps (rangesFor) and concatenating the bodies in order. Mirrors how web_peer_connection re-assembles incoming_payload fragments into a single block.

Link copied to clipboard
fun rangesFor(piece: Int, offset: Int, length: Int): List<HttpRange>

Map a BitTorrent block request to the list of HTTP byte ranges that satisfy it. This is the pure, network-free core of fetchBlock. It delegates to WebSeedMapper, the testable port of the URL + Range computation in web_peer_connection::write_request together with file_storage::map_block.