torrent

package module
v0.0.0-...-3c753bc Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2014 License: BSD-3-Clause Imports: 25 Imported by: 0

README

Taipei Torrent

This is a simple command-line-interface BitTorrent client coded in the go programming language.

Features:

  • Supports multiple torrent files
  • Magnet links
  • DHT
  • IPv6
  • UDP trackers
  • UPnP / NAT-PMP automatic firewall configuration
  • Socks5 proxy support

Additional Features:

  • It can act as a tracker if you start it with the --createTracker flag

FAQ:

Q: Why is it named Taipei Torrent?

A: I started writing it while visiting beautiful Taipei, Taiwan

Q: What is the license?

A: See the LICENSE file.

Current Status

  • Tested on Go 1.3
  • Tested on Windows, Linux and Mac OS X.
  • People tell me they've run it on Android, too.

Development Roadmap

  • Full UPnP support (need to be able to search for an unused listener port, detect we have already acquired the port, defend the report against router reboots, release the listener port when we quit.)
  • Clean up source code
  • Deal with TODOs
  • Perhaps a web-based status UI.

Download, Install, and Build Instructions

  1. Download and install the Go tools from http://golang.org

  2. Use the "go" command to download, install, and build the Taipei-Torrent app:

    go get github.com/remerge/torrent

Usage Instructions

Taipei-Torrent mydownload.torrent
Taipei-Torrent --useDHT "magnet:?xt=urn:btih:bbb6db69965af769f664b6636e7914f8735141b3"

or

Taipei-Torrent -help

Third-party Packages

http://code.google.com/p/bencode-go - Bencode encoder/decoder

Google+ Community

https://plus.google.com/u/0/communities/100997865549971977580

Documentation

Overview

Compute missing pieces for a torrent.

Index

Constants

View Source
const (
	MAX_NUM_PEERS    = 60
	TARGET_NUM_PEERS = 15
)
View Source
const (
	CHOKE = iota
	UNCHOKE
	INTERESTED
	NOT_INTERESTED
	HAVE
	BITFIELD
	REQUEST
	PIECE
	CANCEL
	PORT      // Not implemented. For DHT support.
	EXTENSION = 20
)

BitTorrent message types. Sources: http://bittorrent.org/beps/bep_0003.html http://wiki.theory.org/BitTorrentSpecification

View Source
const (
	METADATA_REQUEST = iota
	METADATA_DATA
	METADATA_REJECT
)
View Source
const (
	EXTENSION_HANDSHAKE = iota
)
View Source
const HIGH_BANDWIDTH_SLOTS = 3
View Source
const MAX_OUR_REQUESTS = 2
View Source
const MAX_PEER_REQUESTS = 10
View Source
const MinimumPieceLength = 16 * 1024
View Source
const OPTIMISTIC_UNCHOKE_COUNT = 3

How many cycles of this algorithm before we pick a new optimistic

View Source
const OPTIMISTIC_UNCHOKE_INDEX = HIGH_BANDWIDTH_SLOTS
View Source
const STANDARD_BLOCK_LENGTH = 16 * 1024
View Source
const TargetPieceCountLog2 = 10
View Source
const TargetPieceCountMax = TargetPieceCountMin << 1

Target piece count should be < TargetPieceCountMax

View Source
const TargetPieceCountMin = 1 << TargetPieceCountLog2

Variables

This section is empty.

Functions

func CreateListener

func CreateListener(flags *TorrentFlags) (listener net.Listener, externalPort int, err error)

func ListenForPeerConnections

func ListenForPeerConnections(flags *TorrentFlags) (conChan chan *btConn, listener net.Listener, listenPort int, err error)

listenForPeerConnections listens on a TCP port for incoming connections and demuxes them to the appropriate active torrentSession based on the InfoHash in the header.

func NewPeerState

func NewPeerState(conn net.Conn) *peerState

func SaveTorrent

func SaveTorrent(meta *MetaInfo) string

func WriteMetaInfoBytes

func WriteMetaInfoBytes(root string, w io.Writer) (err error)

Types

type Accumulator

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

An accumulator that keeps track of the rate of increase.

func NewAccumulator

func NewAccumulator(now time.Time, maxRatePeriod time.Duration) (acc *Accumulator)

func (*Accumulator) Add

func (a *Accumulator) Add(now time.Time, amount int64)

func (*Accumulator) DurationUntilRate

func (a *Accumulator) DurationUntilRate(now time.Time, newRate float64) time.Duration

func (*Accumulator) GetRate

func (a *Accumulator) GetRate(now time.Time) float64

func (*Accumulator) GetRateNoUpdate

func (a *Accumulator) GetRateNoUpdate() float64

type ActivePiece

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

type Bitset

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

func NewBitset

func NewBitset(n int) *Bitset

func NewBitsetFromBytes

func NewBitsetFromBytes(n int, data []byte) *Bitset

Creates a new bitset from a given byte stream. Returns nil if the data is invalid in some way.

func (*Bitset) AndNot

func (b *Bitset) AndNot(b2 *Bitset)

func (*Bitset) Bytes

func (b *Bitset) Bytes() []byte

func (*Bitset) Clear

func (b *Bitset) Clear(index int)

func (*Bitset) FindNextClear

func (b *Bitset) FindNextClear(index int) int

TODO: Make this fast

func (*Bitset) FindNextSet

func (b *Bitset) FindNextSet(index int) int

TODO: Make this fast

func (*Bitset) InRange

func (b *Bitset) InRange(index int) bool

func (*Bitset) IsEndValid

func (b *Bitset) IsEndValid() bool

func (*Bitset) IsSet

func (b *Bitset) IsSet(index int) bool

func (*Bitset) Len

func (b *Bitset) Len() int

func (*Bitset) Set

func (b *Bitset) Set(index int)

type ByDownloadBPS

type ByDownloadBPS []Choker

func (ByDownloadBPS) Len

func (a ByDownloadBPS) Len() int

func (ByDownloadBPS) Less

func (a ByDownloadBPS) Less(i, j int) bool

func (ByDownloadBPS) Swap

func (a ByDownloadBPS) Swap(i, j int)

type ChokePolicy

type ChokePolicy interface {
	// Only pass in interested peers.
	// mutate the chokers into a list where the first N are to be unchoked.
	Choke(chokers []Choker) (unchokeCount int, err error)
}

type Choker

type Choker interface {
	DownloadBPS() float32 // bps
}

The choking policy's view of a peer. For current policies we only care about identity and download bandwidth.

type ClassicChokePolicy

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

Our interpretation of the classic bittorrent choke policy. Expects to be called once every 10 seconds. See the section "Choking and optimistic unchoking" in https://wiki.theory.org/BitTorrentSpecification

func (*ClassicChokePolicy) Choke

func (ccp *ClassicChokePolicy) Choke(chokers []Choker) (unchokeCount int, err error)

type ClientStatusReport

type ClientStatusReport struct {
	Event      string
	InfoHash   string
	PeerId     string
	Port       uint16
	Uploaded   uint64
	Downloaded uint64
	Left       uint64
}

type Dialer

type Dialer func(network, addr string) (net.Conn, error)

type ExtensionHandshake

type ExtensionHandshake struct {
	M      map[string]int `bencode:"m"`
	P      uint16         `bencode:"p"`
	V      string         `bencode:"v"`
	Yourip string         `bencode:"yourip"`
	Ipv6   string         `bencode:"ipv6"`
	Ipv4   string         `bencode:"ipv4"`
	Reqq   uint16         `bencode:"reqq"`

	MetadataSize uint `bencode:"metadata_size"`
}

type File

type File interface {
	io.ReaderAt
	io.WriterAt
	io.Closer
}

Interface for a file. Multiple goroutines may access a File at the same time.

type FileDict

type FileDict struct {
	Length int64
	Path   []string
	Md5sum string
}

type FileStore

type FileStore interface {
	io.ReaderAt
	io.WriterAt
	io.Closer
}

A torrent file store.

func NewFileStore

func NewFileStore(info *InfoDict, fileSystem FileSystem) (f FileStore, totalSize int64, err error)

type FileStoreFileAdapter

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

func (*FileStoreFileAdapter) Close

func (f *FileStoreFileAdapter) Close() (err error)

func (*FileStoreFileAdapter) ReadAt

func (f *FileStoreFileAdapter) ReadAt(p []byte, off int64) (n int, err error)

func (*FileStoreFileAdapter) WriteAt

func (f *FileStoreFileAdapter) WriteAt(p []byte, off int64) (n int, err error)

type FileStoreFileSystemAdapter

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

Adapt a MetaInfoFileSystem into a torrent file store FileSystem

func (*FileStoreFileSystemAdapter) Open

func (f *FileStoreFileSystemAdapter) Open(name []string, length int64) (file File, err error)

type FileSystem

type FileSystem interface {
	Open(name []string, length int64) (file File, err error)
}

Interface for a file system. A file system contains files.

func NewOSFileSystem

func NewOSFileSystem(directory string) (fs FileSystem, err error)

type InfoDict

type InfoDict struct {
	PieceLength int64 `bencode:"piece length"`
	Pieces      string
	Private     int64
	Name        string
	// Single File Mode
	Length int64
	Md5sum string
	// Multiple File mode
	Files []FileDict
}

type MetaDataExchange

type MetaDataExchange struct {
	Transferring bool
	Pieces       [][]byte
}

type MetaInfo

type MetaInfo struct {
	Info         InfoDict
	InfoHash     string
	Announce     string
	AnnounceList [][]string `bencode:"announce-list"`
	CreationDate string     `bencode:"creation date"`
	Comment      string
	CreatedBy    string `bencode:"created by"`
	Encoding     string
}

func CreateMetaInfoFromFileSystem

func CreateMetaInfoFromFileSystem(fs MetaInfoFileSystem, root string, pieceLength int64, wantMD5Sum bool) (metaInfo *MetaInfo, err error)

Create a MetaInfo for a given file and file system. If fs is nil then the OSMetaInfoFileSystem will be used. If pieceLength is 0 then an optimal piece length will be chosen.

func GetMetaInfo

func GetMetaInfo(dialer Dialer, torrent string) (metaInfo *MetaInfo, err error)

func NewTorrentFor

func NewTorrentFor(filename string, tracker string) (*MetaInfo, string)

func (*MetaInfo) Bencode

func (m *MetaInfo) Bencode(w io.Writer) (err error)

Encode to Bencode, but only encode non-default values.

func (*MetaInfo) UpdateInfoHash

func (m *MetaInfo) UpdateInfoHash(metaInfo *MetaInfo) (err error)

Updates the InfoHash field. Call this after manually changing the Info data.

type MetaInfoFile

type MetaInfoFile interface {
	io.Closer
	io.Reader
	io.ReaderAt
	Readdirnames(n int) (names []string, err error)
	Stat() (os.FileInfo, error)
}

type MetaInfoFileSystem

type MetaInfoFileSystem interface {
	Open(name string) (MetaInfoFile, error)
	Stat(name string) (os.FileInfo, error)
}

type MetadataMessage

type MetadataMessage struct {
	MsgType   uint8 `bencode:"msg_type"`
	Piece     uint  `bencode:"piece"`
	TotalSize uint  `bencode:"total_size"`
}

type NeverChokePolicy

type NeverChokePolicy struct{}

Our naive never-choke policy

func (*NeverChokePolicy) Choke

func (n *NeverChokePolicy) Choke(chokers []Choker) (unchokeCount int, err error)

type OSMetaInfoFileSystem

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

func (*OSMetaInfoFileSystem) Open

func (o *OSMetaInfoFileSystem) Open(name string) (MetaInfoFile, error)

func (*OSMetaInfoFileSystem) Stat

func (o *OSMetaInfoFileSystem) Stat(name string) (os.FileInfo, error)

type SessionInfo

type SessionInfo struct {
	PeerId     string
	Port       uint16
	Uploaded   uint64
	Downloaded uint64
	Left       uint64

	HaveTorrent bool

	OurExtensions map[int]string
	ME            *MetaDataExchange
}

type TorrentClient

type TorrentClient struct {
	Flags      *TorrentFlags
	ListenPort int
	DoneConn   chan *TorrentSession
	Sessions   map[string]*TorrentSession
	// contains filtered or unexported fields
}

func NewTorrentClient

func NewTorrentClient(dir string, port int) *TorrentClient

func (*TorrentClient) Download

func (c *TorrentClient) Download(meta *MetaInfo) *TorrentSession

func (*TorrentClient) Serve

func (c *TorrentClient) Serve(torrentfile string) *TorrentSession

func (*TorrentClient) Shutdown

func (c *TorrentClient) Shutdown()

func (*TorrentClient) Unserve

func (c *TorrentClient) Unserve(session *TorrentSession)

type TorrentFlags

type TorrentFlags struct {
	Port                int
	FileDir             string
	SeedRatio           float64
	UseDeadlockDetector bool

	// The dial function to use. Nil means use net.Dial
	Dial Dialer
}

type TorrentSession

type TorrentSession struct {
	Done chan bool

	M *MetaInfo

	TorrentFile string
	// contains filtered or unexported fields
}

func NewTorrentSession

func NewTorrentSession(flags *TorrentFlags, torrent string, listenPort uint16) (ts *TorrentSession, err error)

func (*TorrentSession) AcceptNewPeer

func (t *TorrentSession) AcceptNewPeer(btconn *btConn)

func (*TorrentSession) AddPeer

func (t *TorrentSession) AddPeer(btconn *btConn)

Can be called from any goroutine

func (*TorrentSession) ChoosePiece

func (t *TorrentSession) ChoosePiece(p *peerState) (piece int)

func (*TorrentSession) ClosePeer

func (t *TorrentSession) ClosePeer(peer *peerState)

func (*TorrentSession) DoExtension

func (t *TorrentSession) DoExtension(msg []byte, p *peerState) (err error)

func (*TorrentSession) DoMessage

func (t *TorrentSession) DoMessage(p *peerState, message []byte) (err error)

func (*TorrentSession) DoMetadata

func (t *TorrentSession) DoMetadata(msg []byte, p *peerState)

func (*TorrentSession) DoTorrent

func (t *TorrentSession) DoTorrent()

func (*TorrentSession) Header

func (ts *TorrentSession) Header() (header []byte)

func (*TorrentSession) HintNewPeer

func (ts *TorrentSession) HintNewPeer(peer string)

Try to connect if the peer is not already in our peers. Can be called from any goroutine.

func (*TorrentSession) Quit

func (t *TorrentSession) Quit() (err error)

func (*TorrentSession) RecordBlock

func (t *TorrentSession) RecordBlock(p *peerState, piece, begin, length uint32) (err error)

func (*TorrentSession) RequestBlock

func (t *TorrentSession) RequestBlock(p *peerState) (err error)

func (*TorrentSession) RequestBlock2

func (t *TorrentSession) RequestBlock2(p *peerState, piece int, endGame bool) (err error)

func (*TorrentSession) Shutdown

func (t *TorrentSession) Shutdown() (err error)

type TrackerResponse

type TrackerResponse struct {
	FailureReason  string `bencode:"failure reason"`
	WarningMessage string `bencode:"warning message"`
	Interval       uint
	MinInterval    uint   `bencode:"min interval"`
	TrackerId      string `bencode:"tracker id"`
	Complete       uint
	Incomplete     uint
	Peers          string
	Peers6         string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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