bytedribble

package module
v0.0.0-...-abf2807 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 27, 2022 License: MIT Imports: 21 Imported by: 0

README

bytedribble is a bad BitTorrent client

bytedribble seeks to implement an acceptable BitTorrent client with increasing correctness and completeness. This is purely a learning exercise and is currently (forever?) incomplete.

I am currently implementing the core BitTorrent protocol BEP-3 with the simple goal of downloading a file from a public tracker and participating in seeding as a well-behaved peer. Afterwards, I'm interested in

  • usability features like partial file persistence to allow resumes and avoid storing all data in memory
  • modern need-to-have features to be able to download most torrents in the wild
    • support for compact peer lists - simple encoding/parsing change
    • support for UDP trackers in practice, many modern trackers are UDP-only, meaning that trackers exclusively supporting HTTP trackers are obsolete
  • peer-to-peer extensions like the DHT and PEX protocols
  • networking-specific enhancements with uTP and support for holepunching (NAT traversal)
  • "completing" basic implementation with the piece selection algorithms outlined in the BitTorrent Economics paper and Fast Extension
  • extending the interface and design to be server-focused
  • 2-3 rounds of benchmarking/profiling and performance tuning
  • implementing a tracker
  • 🦀 rust rewrite??

In addition to unit tests, I use a "lab" of docker containers to test end-to-end functionality by running a simple tracker and other (functional) BitTorrent client/peers (Transmission).

Documentation

Index

Constants

View Source
const DefaultBlockLength = 1 << 14

Variables

This section is empty.

Functions

This section is empty.

Types

type Bitfield

type Bitfield []byte

func EmptyBitfield

func EmptyBitfield(numPieces int) Bitfield

func (Bitfield) Empty

func (b Bitfield) Empty() bool

func (Bitfield) Has

func (b Bitfield) Has(pieceIdx int) bool

func (Bitfield) Have

func (b Bitfield) Have(pieceIdx int)

func (Bitfield) Validate

func (b Bitfield) Validate(numPieces int) error

type Block

type Block struct {
	PieceIndex  uint32
	BeginOffset uint32
	Length      uint32
}

type Downloader

type Downloader struct {
	// contains filtered or unexported fields
}

func NewDownloader

func NewDownloader(target Metainfo, self PeerInfo) *Downloader

func (*Downloader) Start

func (d *Downloader) Start(ctx context.Context)

type Event

type Event string
const (
	Started   Event = "started"
	Stopped   Event = "stopped"
	Completed Event = "completed"
	Empty     Event = ""
)

type FakeMetrics

type FakeMetrics struct {
	TotalSize int
}

func (FakeMetrics) Downloaded

func (m FakeMetrics) Downloaded() int

func (FakeMetrics) Left

func (m FakeMetrics) Left() int

func (FakeMetrics) Uploaded

func (m FakeMetrics) Uploaded() int

type Message

type Message struct {
	Type    MessageType
	Payload []byte
}

type MessageType

type MessageType byte
const (
	ChokeMessage MessageType = iota
	UnchokeMessage
	InterestedMessage
	NotInterestedMessage
	HaveMessage
	BitfieldMessage
	RequestMessage
	PieceMessage
	CancelMessage
)

type Metainfo

type Metainfo struct {
	TrackerURL     *url.URL          // announce
	Name           string            // info.name
	Hashes         [][sha1.Size]byte // info.pieces
	PieceSizeBytes int               // info.pieces length
	TotalSizeBytes int               // info.length
	Files          []struct {
		SizeBytes int      // length
		Path      []string // path
	}
	RawInfo map[string]any // original map of entire "info" field
}

Metainfo describes a torrent.

See: https://www.bittorrent.org/beps/bep_0003.html#metainfo-files

func ParseMetainfo

func ParseMetainfo(raw io.Reader) (Metainfo, error)

ParseMetainfo parses a bencoded metainfo file

func (Metainfo) InfoHash

func (m Metainfo) InfoHash() []byte

type Peer

type Peer struct {
	// contains filtered or unexported fields
}

func NewPeer

func NewPeer(info PeerInfo, self PeerID, infohash []byte, numPieces int) *Peer

func (*Peer) Cancel

func (p *Peer) Cancel(param Block) error

func (*Peer) Choke

func (p *Peer) Choke() error

func (*Peer) Close

func (p *Peer) Close()

func (*Peer) Have

func (p *Peer) Have(pieceIdx uint32) error

func (*Peer) Info

func (p *Peer) Info() PeerInfo

func (*Peer) Initialize

func (p *Peer) Initialize(ctx context.Context) (err error)

Initialize establishes a connection to the peer and performs the initial handshake.

func (*Peer) Interested

func (p *Peer) Interested() error

func (*Peer) KeepAlive

func (p *Peer) KeepAlive() error

func (*Peer) NotInterested

func (p *Peer) NotInterested() error

func (*Peer) Request

func (p *Peer) Request(params Block) error

func (*Peer) Run

func (p *Peer) Run() error

func (*Peer) Subscribe

func (p *Peer) Subscribe(messageCh chan<- Message) error

func (*Peer) Unchoke

func (p *Peer) Unchoke() error

func (*Peer) Unchoked

func (p *Peer) Unchoked() <-chan struct{}

func (*Peer) Unsubscribe

func (p *Peer) Unsubscribe(messageCh chan<- Message) error

type PeerID

type PeerID [peerIDLen]byte

func PeerIDFromString

func PeerIDFromString(s string) PeerID

func RandPeerID

func RandPeerID() PeerID

func (PeerID) Bytes

func (i PeerID) Bytes() []byte

func (PeerID) String

func (i PeerID) String() string

type PeerInfo

type PeerInfo struct {
	PeerID PeerID
	IP     net.IP
	Port   int
}

type Piece

type Piece struct {
	Index     uint32
	Size      uint32
	BlockSize uint32
	Hash      [sha1.Size]byte
	// contains filtered or unexported fields
}

func (*Piece) AddBlockPayload

func (p *Piece) AddBlockPayload(block Block, payload []byte)

func (*Piece) MissingBlocks

func (p *Piece) MissingBlocks() []Block

func (*Piece) NumBlocks

func (p *Piece) NumBlocks() int

func (*Piece) Payload

func (p *Piece) Payload() []byte

func (*Piece) Reset

func (p *Piece) Reset()

func (*Piece) String

func (p *Piece) String() string

func (*Piece) Valid

func (p *Piece) Valid() bool

type TorrentMetrics

type TorrentMetrics interface {
	Uploaded() int
	Downloaded() int
	Left() int
}

type TrackerClient

type TrackerClient struct {
	// contains filtered or unexported fields
}

func NewTrackerClient

func NewTrackerClient(client *http.Client, target Metainfo, self PeerInfo, metrics TorrentMetrics) *TrackerClient

func (*TrackerClient) Completed

func (c *TrackerClient) Completed(ctx context.Context) error

func (*TrackerClient) Peers

func (c *TrackerClient) Peers() []PeerInfo

func (*TrackerClient) RequestNewPeers

func (c *TrackerClient) RequestNewPeers(ctx context.Context) ([]PeerInfo, error)

func (*TrackerClient) Run

func (c *TrackerClient) Run(ctx context.Context) error

func (*TrackerClient) Started

func (c *TrackerClient) Started(ctx context.Context) error

func (*TrackerClient) Stopped

func (c *TrackerClient) Stopped(ctx context.Context) error

type Worker

type Worker struct {
	// contains filtered or unexported fields
}

func NewWorker

func NewWorker(peer *Peer) *Worker

func (*Worker) RequestPiece

func (w *Worker) RequestPiece(p *Piece)

func (*Worker) Run

func (w *Worker) Run(ctx context.Context) error

func (*Worker) SetCallback

func (w *Worker) SetCallback(cb func(*Piece, error))

Directories

Path Synopsis
Package bencoding implements the encoding used by bittorrent metadata and protocols.
Package bencoding implements the encoding used by bittorrent metadata and protocols.
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL