torrent

package
v0.0.0-...-9581b95 Latest Latest
Warning

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

Go to latest
Published: May 3, 2015 License: BSD-3-Clause Imports: 37 Imported by: 0

Documentation

Overview

cache

hdcache

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 Dump

func Dump(buff []byte)

Simple utility for dumping a []byte to log. It skips over sections of '0', unlike encoding/hex.Dump()

func ListenForPeerConnections

func ListenForPeerConnections(flags *TorrentFlags) (conChan chan *BtConn, 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 RunTorrents

func RunTorrents(flags *TorrentFlags, torrentFiles []string) (err error)

func WriteMetaInfoBytes

func WriteMetaInfoBytes(root, tracker 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 Announce

type Announce struct {
	Peer     string
	Infohash string
}

type Announcer

type Announcer struct {
	Announces chan *Announce
	// contains filtered or unexported fields
}

func NewAnnouncer

func NewAnnouncer(listenPort uint16) (lpd *Announcer, err error)

func (*Announcer) Announce

func (lpd *Announcer) Announce(ih string)

func (*Announcer) StopAnnouncing

func (lpd *Announcer) StopAnnouncing(ih string)

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 BtConn

type BtConn struct {
	RemoteAddr net.Addr

	Infohash string
	// contains filtered or unexported fields
}

btConn wraps an incoming network connection and contains metadata that helps identify which active torrentSession it's relevant for.

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 CacheProvider

type CacheProvider interface {
	NewCache(infohash string, numPieces int, pieceLength int, totalSize int64) TorrentCache
}

func NewHdCacheProvider

func NewHdCacheProvider(capacity int) CacheProvider

func NewRamCacheProvider

func NewRamCacheProvider(capacity int) CacheProvider

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 Device

type Device struct {
	XMLName     xml.Name    `xml:"device"`
	DeviceType  string      `xml:"deviceType"`
	DeviceList  DeviceList  `xml:"deviceList"`
	ServiceList ServiceList `xml:"serviceList"`
}

type DeviceList

type DeviceList struct {
	Device []Device `xml:"device"`
}

type Envelope

type Envelope struct {
	XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
	Soap    *SoapBody
}

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 ExternalIPAddress

type ExternalIPAddress struct {
	XMLName xml.Name `xml:"NewExternalIPAddress"`
	IP      string
}

type ExternalIPAddressResponse

type ExternalIPAddressResponse struct {
	XMLName   xml.Name `xml:"GetExternalIPAddressResponse"`
	IPAddress string   `xml:"NewExternalIPAddress"`
}

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
	SetCache(TorrentCache)
	Commit(int, []byte, int64)
}

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) Close

func (f *FileStoreFileSystemAdapter) Close() error

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)
	io.Closer
}

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

func NewRAMFileSystem

func NewRAMFileSystem() (fs FileSystem, err error)

type FsProvider

type FsProvider interface {
	NewFS(directory string) (FileSystem, error)
}

Interface for a provider of filesystems.

type HdCache

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

'pieceSize' is the size of the average piece 'capacity' is how many pieces the cache can hold 'actualUsage' is how many pieces the cache has at the moment 'atime' is an array of access times for each stored box 'boxExists' indicates if a box is existent in cache 'isBoxFull' indicates if a box entirely contains written data 'isBoxCommit' indicates if a box has been committed to storage 'isByteSet' for [i] indicates for box 'i' if a byte has been written to 'boxPrefix' is the partial path to the boxes. 'torrentLength' is the number of bytes in the torrent 'cacheProvider' is a pointer to the cacheProvider that created this cache 'infohash' is the infohash of the torrent

func (*HdCache) Close

func (r *HdCache) Close()

func (*HdCache) MarkCommitted

func (r *HdCache) MarkCommitted(piece int)

func (*HdCache) ReadAt

func (r *HdCache) ReadAt(p []byte, off int64) []chunk

func (*HdCache) WriteAt

func (r *HdCache) WriteAt(p []byte, off int64) []chunk

type HdCacheProvider

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

This provider creates an HD cache for each torrent. Each time a cache is created or closed, all cache are recalculated so they total <= capacity (in MiB).

func (*HdCacheProvider) NewCache

func (r *HdCacheProvider) NewCache(infohash string, numPieces int, pieceSize int, torrentLength int64) TorrentCache

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 Magnet

type Magnet struct {
	InfoHashes []string
	Names      []string
	Trackers   [][]string
}

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, tracker 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 proxy.Dialer, torrent string) (metaInfo *MetaInfo, err error)

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 NAT

type NAT interface {
	GetExternalAddress() (addr net.IP, err error)
	AddPortMapping(protocol string, externalPort, internalPort int, description string, timeout int) (mappedExternalPort int, err error)
	DeletePortMapping(protocol string, externalPort, internalPort int) (err error)
}

protocol is either "udp" or "tcp"

func CreatePortMapping

func CreatePortMapping(flags *TorrentFlags) (nat NAT, err error)

createPortMapping creates a NAT port mapping, or nil if none requested or found.

func Discover

func Discover() (nat NAT, err error)

func NewNatPMP

func NewNatPMP(gateway net.IP) (nat NAT)

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 OsFsProvider

type OsFsProvider struct{}

func (OsFsProvider) NewFS

func (o OsFsProvider) NewFS(directory string) (fs FileSystem, err error)

type RamCache

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

'pieceSize' is the size of the average piece 'capacity' is how many pieces the cache can hold 'actualUsage' is how many pieces the cache has at the moment 'atime' is an array of access times for each stored box 'store' is an array of "boxes" ([]byte of 1 piece each) 'isBoxFull' indicates if a box entirely contains written data 'isBoxCommit' indicates if a box has been committed to storage 'isByteSet' for [i] indicates for box 'i' if a byte has been written to 'torrentLength' is the number of bytes in the torrent 'cacheProvider' is a pointer to the cacheProvider that created this cache 'infohash' is the infohash of the torrent

func (*RamCache) Close

func (r *RamCache) Close()

func (*RamCache) MarkCommitted

func (r *RamCache) MarkCommitted(piece int)

func (*RamCache) ReadAt

func (r *RamCache) ReadAt(p []byte, off int64) []chunk

func (*RamCache) WriteAt

func (r *RamCache) WriteAt(p []byte, off int64) []chunk

type RamCacheProvider

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

This provider creates a ram cache for each torrent. Each time a cache is created or closed, all cache are recalculated so they total <= capacity (in MiB).

func (*RamCacheProvider) NewCache

func (r *RamCacheProvider) NewCache(infohash string, numPieces int, pieceSize int, torrentLength int64) TorrentCache

type Root

type Root struct {
	Device Device
}

type Service

type Service struct {
	ServiceType string `xml:"serviceType"`
	ControlURL  string `xml:"controlURL"`
}

type ServiceList

type ServiceList struct {
	Service []Service `xml:"service"`
}

type SessionInfo

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

	UseDHT      bool
	FromMagnet  bool
	HaveTorrent bool

	OurExtensions map[int]string
	ME            *MetaDataExchange
}

type SftpFile

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

func (*SftpFile) Close

func (sff *SftpFile) Close() error

func (*SftpFile) ReadAt

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

func (*SftpFile) WriteAt

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

type SftpFileSystem

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

func (*SftpFileSystem) Close

func (sfs *SftpFileSystem) Close() (err error)

func (*SftpFileSystem) Connect

func (sfs *SftpFileSystem) Connect() error

func (*SftpFileSystem) Open

func (sfs *SftpFileSystem) Open(name []string, length int64) (File, error)

type SftpFsProvider

type SftpFsProvider struct {
	Server     string
	Username   string
	Password   string
	ServerPath string
}

func NewSftpFsProvider

func NewSftpFsProvider(connection string) SftpFsProvider

Connection string: username:password@example.com:8042/over/there/

func (SftpFsProvider) NewFS

func (o SftpFsProvider) NewFS(directory string) (fs FileSystem, err error)

type SoapBody

type SoapBody struct {
	XMLName    xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
	ExternalIP *ExternalIPAddressResponse
}

type TorrentCache

type TorrentCache interface {
	//Read what's cached, returns parts that weren't available to read.
	ReadAt(p []byte, offset int64) []chunk
	//Writes to cache, returns uncommitted data that has been trimmed.
	WriteAt(p []byte, offset int64) []chunk
	//Marks a piece as committed to permanent storage.
	MarkCommitted(piece int)
	//Close the cache and free all the things
	Close()
}

type TorrentFlags

type TorrentFlags struct {
	Port                int
	FileDir             string
	SeedRatio           float64
	UseDeadlockDetector bool
	UseLPD              bool
	UseDHT              bool
	UseUPnP             bool
	UseNATPMP           bool
	TrackerlessMode     bool
	ExecOnSeeding       string

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

	// IP address of gateway used for NAT-PMP
	Gateway string

	//Provides the filesystems added torrents are saved to
	FileSystemProvider FsProvider

	//Whether to check file hashes when adding torrents
	InitialCheck bool

	//Provides cache to each torrent
	Cacher CacheProvider

	//Whether to write and use *.haveBitset resume data
	QuickResume bool

	//How many torrents should be active at a time
	MaxActive int
}

type TorrentSession

type TorrentSession struct {
	M *MetaInfo
	// 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
}

Jump to

Keyboard shortcuts

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