@z-torrent/protocol
v0.0.13
Published
Simple, robust, BitTorrent peer wire protocol implementation
Downloads
1,103
Maintainers
Readme
@z-torrent/protocol
Simple, robust BitTorrent peer wire protocol implementation (TypeScript, ESM). Used by Z-Torrent.
Works in Node.js and in the browser when bundled (e.g. Vite, esbuild, Webpack).
Install
npm install @z-torrent/protocolUsage
The protocol is implemented as a duplex stream, so you pipe to and from it.
| duplex streams | a.pipe(b).pipe(a) |
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
|
(Images from the "harnessing streams" talk by substack.)
import Wire from '@z-torrent/protocol'
import net from 'node:net'
net
.createServer((socket) => {
const wire = new Wire()
socket.pipe(wire).pipe(socket)
wire.on('handshake', (infoHash, peerId) => {
// infoHash and peerId are hex strings from the peer
wire.handshake(infoHash, peerId)
})
wire.on('unchoke', () => {
console.log('peer is no longer choking us: ' + wire.peerChoking)
})
})
.listen(6881)Methods
Handshaking
Send and receive a handshake from the peer. This is the first message.
wire.handshake(infoHash, peerId, { dht: true })
wire.on('handshake', (infoHash, peerId, extensions) => {
console.log(extensions.dht) // supports DHT (BEP-0005)
console.log(extensions.extended) // supports extension protocol (BEP-0010)
})For wire.handshake(), infoHash and peerId must be 20 bytes each, as a hex string, Uint8Array, or Node Buffer.
Choking
wire.peerChoking
wire.amChoking
wire.on('choke', () => {})
wire.on('unchoke', () => {})Interested
wire.peerInterested
wire.amInterested
wire.on('interested', () => {})
wire.on('uninterested', () => {})Bitfield
wire.bitfield(buffer)
wire.on('bitfield', (bitfield) => {})
wire.have(pieceIndex)
wire.on('have', (pieceIndex) => {})
wire.peerPieces.get(i) // true if peer has piece iwire.peerPieces is a BitField, see bitfield.
Requests
wire.request(pieceIndex, offset, length, (err, block) => {
if (err) return
})
wire.cancel(pieceIndex, offset, length)
wire.on('request', (pieceIndex, offset, length, callback) => {
callback(null, block)
})
wire.requests
wire.peerRequestswire.setTimeout(5000)DHT and port
wire.port(dhtPort)
wire.on('port', (dhtPort) => {})
wire.peerExtensions.dht
wire.peerExtensions.extendedKeep-alive
wire.setKeepAlive(true)
wire.on('keep-alive', () => {})Fast extension (BEP 6)
BitTorrent Fast Extension (BEP 6).
wire.handshake(infoHash, peerId, { fast: true })
wire.hasFast
wire.haveNone()
wire.on('have-none', () => {})
wire.haveAll()
wire.on('have-all', () => {})
wire.suggest(pieceIndex)
wire.on('suggest', (pieceIndex) => {})
wire.on('allowed-fast', (pieceIndex) => {})
wire.peerAllowedFastSet
wire.reject(pieceIndex, offset, length)
wire.on('reject', (pieceIndex, offset, length) => {})Extension protocol (BEP 10)
BitTorrent Extension Protocol (BEP 10).
wire.extended(code, buffer)@z-torrent/protocol exposes an extension API (wire.use()) for BEP 10 extensions such as BEP 9 (ut_metadata).
Transfer stats
wire.uploaded
wire.downloaded
wire.uploadSpeed()
wire.downloadSpeed()
wire.on('download', (numberOfBytes) => {})
wire.on('upload', (numberOfBytes) => {})Extension API
Common extensions in this monorepo:
- @z-torrent/ut-metadata — BEP 9 (metadata over the wire)
- @z-torrent/ut-pex — BEP 11 (PEX)
Register an extension with wire.use(). Extensions can hook handshake, extended, etc.
Example with @z-torrent/ut-metadata:
import Wire from '@z-torrent/protocol'
import { createUtMetadata } from '@z-torrent/ut-metadata'
import net from 'node:net'
net
.createServer((socket) => {
const wire = new Wire()
socket.pipe(wire).pipe(socket)
wire.use(createUtMetadata())
wire.ut_metadata.fetch()
wire.ut_metadata.on('metadata', (metadata) => {
// Uint8Array .torrent info payload
})
wire.ut_metadata.on('warning', (err) => {
console.log(err.message)
})
wire.on('handshake', (infoHash, peerId) => {
wire.handshake(infoHash, peerId)
})
})
.listen(6881)See @z-torrent/ut-metadata for implementation details.
License
MIT. Based on bittorrent-protocol by Feross Aboukhadijeh, Mathias Buus, and WebTorrent, LLC. Maintained as @z-torrent/protocol in z-torrent.
