Package-level declarations

Types

Link copied to clipboard

A datagram (host, port) source and sink. This is the seam consumers (DHT, UDP trackers, uTP) program against. UdpSocket is the real implementation; a demultiplexer (see UtpSocketManager) hands out virtual transports over one shared socket, the way libtorrent's session_impl routes one listen socket to uTP, DHT and trackers.

Link copied to clipboard
data class HttpProxyConfig(val host: String, val port: Int, val username: String? = null, val password: String? = null) : ProxyConfig

HTTP CONNECT proxy configuration. username/password enable HTTP Basic Proxy-Authorization; leave them null for an open proxy.

Link copied to clipboard
data class IgdControl(val controlUrl: String, val serviceType: String, val modelName: String? = null)

A resolved IGD control endpoint: the absolute SOAP control URL and the service type (WANIPConnection/WANPPPConnection) to use as the SOAP namespace and SOAPAction prefix. The engine caches this after Upnp.discoverIgd / Upnp.describe.

Link copied to clipboard
data class LocalInterface(val name: String, val address: String, val isLoopback: Boolean, val isIpv4: Boolean)

One local network interface address. This is the slice of libtorrent's ip_interface (enum_net.hpp) a client actually uses: pick a bind address, learn the LAN address for UPnP, skip loopback.

Link copied to clipboard
class MicrosCounter(start: Long = 0) : Function0<Long>

A deterministic microsecond source for tests. Each call returns the previous value plus one. It is not a wall clock and it is not a monotonic clock.

Link copied to clipboard

A real monotonic microsecond clock. Use this for every production UtpStream.

Link copied to clipboard
class NatPmp(udp: UdpSocket, gateway: String, maxAttempts: Int = 9, retryStepMs: Long = 250)

A NAT-PMP client: the live half of libtorrent's natpmp (src/natpmp.cpp), speaking the NAT-PMP (RFC 6886) wire format over the proven UdpSocket. The fixed-layout packet build/parse lives in NatPmpCodec; this class owns the UDP round-trip to the gateway (always port 5351, the NAT-PMP server port udp::endpoint(*route, 5351) in natpmp::start) and the retransmission loop.

Link copied to clipboard

The socket runtime. One SelectorManager drives all non-blocking I/O, the way a single Boost.Asio io_context does in libtorrent. ktor-network's selector is coroutine-native, so there are no callbacks: a read simply suspends.

Link copied to clipboard
sealed interface ProxyConfig

A proxy connectTcp tunnels outbound dials through. See Socks5Config, HttpProxyConfig.

Link copied to clipboard
class ProxyException(message: String) : Exception

Raised when a proxy negotiation fails.

Link copied to clipboard
data class Socks4Config(val host: String, val port: Int, val username: String? = null, val password: String? = null) : ProxyConfig

SOCKS4 / SOCKS4a proxy configuration. username becomes the SOCKS4 USERID; password is unused (SOCKS4 has no password auth). Hostname targets use the SOCKS4a extension.

Link copied to clipboard
data class Socks5Config(val host: String, val port: Int, val username: String? = null, val password: String? = null) : ProxyConfig

SOCKS5 proxy configuration (settings_pack::proxy_*). username/password enable the RFC-1929 username/password auth method; leave them null for a no-auth proxy.

Link copied to clipboard

A live SOCKS5 UDP ASSOCIATE relay (RFC 1928 §6–§7). The control TCP connection (control) is held open for the lifetime of the association (the proxy shuts the UDP relay down when that connection closes), while datagrams flow over relay, a plain UdpSocket.

Link copied to clipboard
class Socks5UdpDatagram(val host: String, val port: Int, val payload: ByteArray)

The decoded origin and payload of an inbound SOCKS5-wrapped UDP datagram (see Socks5UdpAssociation.unwrap).

Link copied to clipboard
class TcpConnection(socket: Socket)

A TCP connection to a peer (or HTTP tracker). Thin coroutine wrapper over a ktor Socket exposing the two operations the wire protocol needs: read exactly N bytes, and write a frame. Replaces the bespoke async read/write buffers in libtorrent's peer_connection.

Link copied to clipboard
class TcpServer(serverSocket: ServerSocket)

A listening TCP socket. It accepts inbound peer connections (libtorrent's listen_socket_t). Used by the engine to receive connections and by tests to stand up a loopback seeder.

Link copied to clipboard
class UdpPacket(val data: ByteArray, val host: String, val port: Int)

A received datagram: payload data and the sender's host:port.

Link copied to clipboard
class UdpSocket(socket: BoundDatagramSocket, socks5: Socks5UdpAssociation? = null) : DatagramTransport

A real UDP socket, for UDP trackers, the DHT, and uTP.

Link copied to clipboard
object Upnp

UPnP IGD port mapping: a port of the SSDP-discovery + SOAP-control half of libtorrent's upnp (upnp.cpp). Opens an inbound port on a NAT gateway so peers can reach us. SSDP runs over UDP multicast; the control step is plain SOAP-over-HTTP.

Link copied to clipboard
data class UpnpMapping(val igd: IgdControl, val externalPort: Int, val internalPort: Int, val internalClient: String, val leaseSeconds: Int, val tcpMapped: Boolean, val udpMapped: Boolean)

The handle returned by Upnp.mapTcpAndUdp: enough state for the engine to refresh the lease (re-call mapTcpAndUdp before leaseSeconds elapses) and to tear the mapping down (Upnp.removeMapping) on shutdown.

Link copied to clipboard
class UtpEofException(message: String) : Exception

Raised by UtpStream.readExactly when the peer closes the stream early.

Link copied to clipboard

uTP extension-header kinds. From libtorrent's utp_extensions_t:

Link copied to clipboard
data class UtpHeader(val type: UtpType, val version: Int = UTP_VERSION, val extension: Int = UtpExtension.NONE, val connectionId: Int, val timestampMicros: Long, val timestampDiffMicros: Long, val wndSize: Long, val seqNr: Int, val ackNr: Int)

A parsed/parseable uTP header: the faithful Kotlin analogue of libtorrent's struct utp_header (include/libtorrent/aux_/utp_stream.hpp).

Link copied to clipboard
class UtpPacket(val header: UtpHeader, val sack: ByteArray?, val payload: ByteArray)

A fully-decoded uTP packet: its header, the optional Selective-ACK bitmask (if the first extension was UtpExtension.SACK), and the payload (bytes after all extension headers).

Link copied to clipboard

Raised when the peer sends ST_RESET.

Link copied to clipboard
class UtpSocketManager(socket: UdpSocket, scope: CoroutineScope)

Demultiplexes one UDP socket across many UtpStreams: the port of libtorrent's utp_socket_manager (src/utp_socket_manager.cpp) plus the session-level routing that shares the listen socket between uTP and the DHT.

Link copied to clipboard
class UtpStream(socket: UdpSocket, remoteHost: String, remotePort: Int, scope: CoroutineScope, nowMicros: () -> Long = MicrosCounter(), connectionId: Int = ((nowMicros() and 0xFFFF).toInt()), minTimeoutMicros: Long = DEFAULT_MIN_TIMEOUT_MICROS, selfTick: Boolean = true, tickIntervalMs: Long = DEFAULT_TICK_INTERVAL_MS, nagleEnabled: Boolean = true) : ByteStream

uTP (Micro Transport Protocol, BEP-29) connection over a single UdpSocket to one remote (host, port). This is a faithful core port of libtorrent's utp_socket_impl (src/utp_stream.cpp), with enough state machine to actually move bytes. It implements ByteStream so a PeerConnection runs over uTP with no changes (the same seam TcpConnection.asByteStream satisfies).

Link copied to clipboard

uTP packet types (BEP-29). Mirrors libtorrent's utp_socket_state_t (include/libtorrent/aux_/utp_stream.hpp):

Properties

Link copied to clipboard
const val UTP_HEADER_SIZE: Int = 20

The fixed uTP header size: 20 bytes. Matches sizeof(utp_header) in libtorrent (utp_stream.cpp uses acquire_packet(sizeof(utp_header)) everywhere).

Link copied to clipboard
const val UTP_VERSION: Int = 1

The uTP protocol version this codec speaks (always 1, per BEP-29).

Functions

Link copied to clipboard
suspend fun NetworkRuntime.bindTcp(port: Int, host: String = "0.0.0.0"): TcpServer

Bind a listening TCP socket on host:port (port 0 = an ephemeral free port).

Link copied to clipboard
suspend fun NetworkRuntime.bindUdp(port: Int = 0, host: String = "0.0.0.0"): UdpSocket

Bind a UDP socket on host:port (port 0 = any free port). host defaults to the IPv4 wildcard 0.0.0.0; pass "::" to bind the IPv6 (dual-stack on most OSes) wildcard, the way libtorrent's udp_socket::bind honours the listen interface's address family.

Link copied to clipboard
fun buildUtpPacket(header: UtpHeader, payload: ByteArray = EMPTY_BYTES, sack: ByteArray? = null): ByteArray

Build a full uTP packet: header (its UtpHeader.extension is overridden to advertise a SACK iff sack is non-null), then, if present, the SACK extension TLV (next_ext=0, len, bitmask), then payload.

Link copied to clipboard
suspend fun NetworkRuntime.connectTcp(host: String, port: Int, connectTimeoutMs: Long = 0, bypassProxy: Boolean = false): TcpConnection

Open a TCP connection to host:port, tunnelling through NetworkRuntime.proxy if set.

Link copied to clipboard

Android interface enumeration via NetworkInterface (same as JVM).

Enumerate local interface addresses: a port of enum_net() (enum_net.cpp). This is an expect/actual declaration because listing interfaces is a per-OS syscall with no portable KMP API (NetworkInterface on JVM/Android, getifaddrs on Apple).

Apple interface enumeration.

JVM/desktop interface enumeration via NetworkInterface.

Link copied to clipboard
fun parseUtpPacket(buf: ByteArray, offset: Int = 0, length: Int = buf.size - offset): UtpPacket?

Parse a datagram into a UtpPacket, walking the extension chain to find a SACK bitmask and to locate the payload. Returns null on any malformed framing (short header, unknown type, truncated extension). These are the same rejects libtorrent applies in incoming_packet().

Link copied to clipboard

The non-loopback IPv4 addresses: the usual candidates to advertise/bind.

Link copied to clipboard
fun seqLessWrap(lhs: Int, rhs: Int, mask: Int = UtpStream.ACK_MASK): Boolean

compare_less_wrap(lhs, rhs, ACK_MASK) from utp_stream.cpp: true iff lhs is "less than" rhs in 16-bit sequence space, treating the shorter walking direction as the ordering. The exact C++ logic: