KiteTorrentEngine

class KiteTorrentEngine(scope: CoroutineScope, val peerId: Sha1Hash = generatePeerId(), val listenPort: Int = 6881, httpTracker: HttpTracker? = null, enableDht: Boolean = false, enableUtp: Boolean = false, clock: () -> Long = { 0L }, val settings: SettingsPack = SettingsPack(), httpClient: HttpClient? = null, gateway: String? = null)

The top-level engine, the KiteTorrent equivalent of libtorrent's session. It owns the shared NetworkRuntime, the RateLimiter, the ConnectionBudget, an optional DhtNode and UtpSocketManager, and the set of active TorrentSessions. This is the single object an app talks to.

Configuration flows through the ported SettingsPack, exactly like session(settings_pack): connections_limit caps the session-wide peer count, upload_rate_limit/download_rate_limit seed the limiter (also settable live via setUploadRateLimit/setDownloadRateLimit), and the per-torrent engine reads its request/choke/timeout knobs from the same pack.

With enableUtp, one UDP socket on listenPort carries µTP: outgoing connections dial uTP first (TCP fallback) and inbound uTP connects are accepted and routed by info-hash exactly like the TCP accept loop. When the DHT is enabled too, both share that socket through the manager's demultiplexer. This is libtorrent's single-listen-socket model.

Parameters

clock

epoch-seconds provider for DHT expiry ({ System.currentTimeMillis()/1000 }).

Constructors

Link copied to clipboard
constructor(scope: CoroutineScope, peerId: Sha1Hash = generatePeerId(), listenPort: Int = 6881, httpTracker: HttpTracker? = null, enableDht: Boolean = false, enableUtp: Boolean = false, clock: () -> Long = { 0L }, settings: SettingsPack = SettingsPack(), httpClient: HttpClient? = null, gateway: String? = null)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard

Max concurrently-active (non-paused) torrents (active_limit); -1 = unlimited. Torrents added past the limit are queued (paused), and the oldest queued one resumes whenever an active torrent pauses. This is the port of libtorrent's auto-managed torrent queue.

Link copied to clipboard

The actual TCP port we're listening on (resolved after start; equals listenPort unless it was 0).

Link copied to clipboard

The current external-IP majority winner, fed to DHT secure-id + self-connect suppression.

Link copied to clipboard

Session-wide IP blocklist. Add ranges via IpFilter.addRule. Enforced on dial and accept.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

The session-wide bandwidth scheduler (the live bandwidth_manager wiring).

Link copied to clipboard

Functions

Link copied to clipboard
suspend fun addMagnet(magnet: MagnetLink, diskFactory: (TorrentInfo) -> DiskIo): TorrentSession?

Convenience magnet add with built-in peer discovery. Pools peers for the magnet's info-hash from the DHT (when enableDht) and from the magnet's trackers, then delegates to the peer-list addMagnet overload, which fetches the metadata via BEP-9 ut_metadata and starts the download. Returns null if no peer was reachable or none could supply the metadata.

suspend fun addMagnet(magnet: MagnetLink, peers: List<PeerEndpoint>, diskFactory: (TorrentInfo) -> DiskIo): TorrentSession?

Start a download from a magnet link. Connects to peers (from the magnet's trackers or the DHT, since discovery is the caller's or the engine's job), fetches the metadata from the first cooperative peer via BEP-9 ut_metadata, builds a TorrentInfo, then begins a normal download with the disk diskFactory produces. Returns null if no peer could supply the metadata.

Link copied to clipboard
suspend fun addTorrent(torrent: TorrentInfo, disk: DiskIo, resume: AddTorrentParams? = null): TorrentSession

Add a torrent and begin downloading it. Announces to trackers immediately. When the DHT is running it also starts a get_peers lookup and feeds those results in.

Link copied to clipboard

Map the settings_pack PROXY_* knobs (proxy_type / proxy_hostname / proxy_port / proxy_username / proxy_password) onto NetworkRuntime.proxy, the port of session_impl::update_proxy. proxy_type NONE clears any proxy; SOCKS4/SOCKS5(/_pw)/HTTP(_pw) build the matching ProxyConfig. Empty hostnames leave the proxy untouched (incomplete config).

Link copied to clipboard
suspend fun applySettings(pack: SettingsPack)

Re-apply a (possibly partial) pack of settings to the running engine and its sessions. This is the port of session::apply_settings. It copies every override in pack into this engine's live settings, then re-drives the knobs that are wired here: rate limits, connections_limit, proxy_*, per-torrent unchoke slots and connection caps. Knobs read once at construction time (request/choke timeouts) take effect for torrents added afterwards.

Link copied to clipboard
suspend fun bootstrapDht(routers: List<Pair<String, Int>>)

Join the DHT via well-known router nodes (e.g. router.bittorrent.com:6881).

Link copied to clipboard
suspend fun discoverPeers(infoHash: Sha1Hash, trackers: List<String> = emptyList()): List<PeerEndpoint>

Best-effort peer discovery for infoHash: a DHT get_peers lookup (when the DHT is up) unioned with announces to trackers (http/https via the injected HttpTracker, udp via an ephemeral UdpTracker). Any single source failing is swallowed; the deduplicated union is returned.

Link copied to clipboard
suspend fun ensureSocks5Udp(relay: UdpSocket? = null): Socks5UdpAssociation?

Lazily open a SOCKS5 UDP ASSOCIATE relay over the configured proxy so UDP transports (uTP/DHT/UDP-trackers) can be tunnelled, the port of libtorrent's socks5::socks_forward_udp. Returns the live association (also stored for teardown), or null if the proxy isn't SOCKS5 or the negotiation failed. The relay socket and control connection are owned by the association.

Link copied to clipboard
suspend fun numConnections(): Int

Connections currently held against connections_limit (observability/tests).

Link copied to clipboard
suspend fun numUtpStreams(): Int

Live µTP streams (0 when µTP is disabled).

Link copied to clipboard
suspend fun pauseSession()

Pause every torrent (session::pause). Each torrent sends event=stopped and flushes.

Link copied to clipboard
suspend fun popAlerts(): List<Alert>

Drain and return all buffered alerts, oldest first (the port of session::pop_alerts). The queue is emptied; a fresh batch accumulates for the next call.

Link copied to clipboard

Buffer one alert (off the hot path). Called by each TorrentSession.onAlert hook. Honours the alert_mask from settings: an alert whose Alert.category shares no bit with the mask is dropped (mirroring alert_manager::should_post). The oldest are evicted past maxAlertQueue.

Link copied to clipboard

Re-seed the DHT routing table from a saveDhtState blob; no-op when the DHT is off.

Link copied to clipboard
suspend fun resumeSession()

Resume every torrent (session::resume).

Link copied to clipboard

Serialize live DHT routing state for the platform to persist; null when the DHT is off.

Link copied to clipboard
suspend fun scrape(infoHash: Sha1Hash, trackers: List<String>): ScrapeResponse?

Scrape swarm statistics (seeders / completed / leechers) for infoHash from the first responsive entry in trackers: UDP via an ephemeral socket (BEP-15), HTTP via the injected client (BEP-48). Returns null if no tracker answered. The counterpart of libtorrent's tracker_manager scrape path.

Link copied to clipboard

Update the session-wide connections_limit live. The shared ConnectionBudget holds an immutable limit (owned elsewhere), so this records the new value in settings and recreates the budget for future torrents; torrents already running keep the prior budget object. Once the owning class grows a setLimit, swap this to mutate in place. The port of session_impl::update_connections_limit.

Link copied to clipboard
fun setDownloadRateLimit(bytesPerSecond: Int)

Cap session-wide download at bytesPerSecond (0 = unlimited). download_rate_limit.

Link copied to clipboard
fun setHttpProxy(host: String?, port: Int = 0, username: String? = null, password: String? = null)

Route all outbound TCP dials through an HTTP CONNECT proxy (HTTP Basic auth when given).

Link copied to clipboard
fun setSocks4Proxy(host: String?, port: Int = 0, username: String? = null)

Route all outbound TCP dials through a SOCKS4/4a proxy (username = SOCKS4 USERID).

Link copied to clipboard
fun setSocks5Proxy(host: String?, port: Int = 0, username: String? = null, password: String? = null)

Route all outbound TCP peer/tracker dials through a SOCKS5 proxy (RFC 1928; RFC-1929 username/password auth when username is given). Pass null to go direct. UDP transports (µTP/DHT) are not yet proxied. The port of settings_pack's proxy_* knobs.

Link copied to clipboard
fun setUploadRateLimit(bytesPerSecond: Int)

Cap session-wide upload at bytesPerSecond (0 = unlimited). upload_rate_limit.

Link copied to clipboard
fun shutdown()

Stop everything and release the sockets.

Link copied to clipboard
suspend fun shutdownGraceful(): ByteArray?

Graceful async teardown: delete NAT mappings, persist DHT state (returned for the caller to write), shut every torrent down cleanly, close the proxy UDP relay, then release sockets. Complements the synchronous shutdown. Returns the serialized DHT state (or null).

Link copied to clipboard
suspend fun start()

Bring up the listen socket(s) and the DHT (if enabled). Call bootstrapDht to join the DHT.

Link copied to clipboard

The active torrent for infoHash, or null.

Link copied to clipboard

All active torrents.

Link copied to clipboard
fun voteExternalIp(address: String)

Record an external-IP observation (from a DHT ip reply, a tracker's external ip, or a port-mapper's reported address) into the majority vote. When a new winner emerges it is adopted as externalIp and propagated to the DHT secure-id derivation (BEP-42). Minimal inline io.github.yuroyami.kitetorrent.session.dht ip_voter: the address with the most votes wins.