More cleaning of public interface
This commit is contained in:
parent
3e753bb8ad
commit
ad6ac3f2cd
76
client.go
76
client.go
@ -114,7 +114,7 @@ type Client struct {
|
|||||||
listeners []net.Listener
|
listeners []net.Listener
|
||||||
utpSock *utp.Socket
|
utpSock *utp.Socket
|
||||||
disableTrackers bool
|
disableTrackers bool
|
||||||
downloadStrategy DownloadStrategy
|
downloadStrategy downloadStrategy
|
||||||
dHT *dht.Server
|
dHT *dht.Server
|
||||||
disableUTP bool
|
disableUTP bool
|
||||||
disableTCP bool
|
disableTCP bool
|
||||||
@ -192,6 +192,8 @@ func (cl *Client) sortedTorrents() (ret []*torrent) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes out a human readable status of the client, such as for writing to a
|
||||||
|
// HTTP status page.
|
||||||
func (cl *Client) WriteStatus(_w io.Writer) {
|
func (cl *Client) WriteStatus(_w io.Writer) {
|
||||||
cl.mu.RLock()
|
cl.mu.RLock()
|
||||||
defer cl.mu.RUnlock()
|
defer cl.mu.RUnlock()
|
||||||
@ -290,7 +292,7 @@ type SectionOpener interface {
|
|||||||
OpenSection(off, n int64) (io.ReadCloser, error)
|
OpenSection(off, n int64) (io.ReadCloser, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dataReadAt(d Data, b []byte, off int64) (n int, err error) {
|
func dataReadAt(d data.Data, b []byte, off int64) (n int, err error) {
|
||||||
if ra, ok := d.(io.ReaderAt); ok {
|
if ra, ok := d.(io.ReaderAt); ok {
|
||||||
return ra.ReadAt(b, off)
|
return ra.ReadAt(b, off)
|
||||||
}
|
}
|
||||||
@ -449,7 +451,6 @@ func NewClient(cfg *Config) (cl *Client, err error) {
|
|||||||
cl = &Client{
|
cl = &Client{
|
||||||
noUpload: cfg.NoUpload,
|
noUpload: cfg.NoUpload,
|
||||||
disableTrackers: cfg.DisableTrackers,
|
disableTrackers: cfg.DisableTrackers,
|
||||||
downloadStrategy: cfg.DownloadStrategy,
|
|
||||||
halfOpenLimit: socketsPerTorrent,
|
halfOpenLimit: socketsPerTorrent,
|
||||||
dataDir: cfg.DataDir,
|
dataDir: cfg.DataDir,
|
||||||
disableUTP: cfg.DisableUTP,
|
disableUTP: cfg.DisableUTP,
|
||||||
@ -483,7 +484,7 @@ func NewClient(cfg *Config) (cl *Client, err error) {
|
|||||||
if cfg.PeerID != "" {
|
if cfg.PeerID != "" {
|
||||||
CopyExact(&cl.peerID, cfg.PeerID)
|
CopyExact(&cl.peerID, cfg.PeerID)
|
||||||
} else {
|
} else {
|
||||||
o := copy(cl.peerID[:], BEP20)
|
o := copy(cl.peerID[:], bep20)
|
||||||
_, err = rand.Read(cl.peerID[o:])
|
_, err = rand.Read(cl.peerID[o:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("error generating peer id")
|
panic("error generating peer id")
|
||||||
@ -491,7 +492,7 @@ func NewClient(cfg *Config) (cl *Client, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cl.downloadStrategy == nil {
|
if cl.downloadStrategy == nil {
|
||||||
cl.downloadStrategy = &DefaultDownloadStrategy{}
|
cl.downloadStrategy = &defaultDownloadStrategy{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the laddr string to listen on for the next Listen call.
|
// Returns the laddr string to listen on for the next Listen call.
|
||||||
@ -557,7 +558,7 @@ func (cl *Client) stopped() bool {
|
|||||||
|
|
||||||
// Stops the client. All connections to peers are closed and all activity will
|
// Stops the client. All connections to peers are closed and all activity will
|
||||||
// come to a halt.
|
// come to a halt.
|
||||||
func (me *Client) Stop() {
|
func (me *Client) Close() {
|
||||||
me.mu.Lock()
|
me.mu.Lock()
|
||||||
defer me.mu.Unlock()
|
defer me.mu.Unlock()
|
||||||
close(me.quit)
|
close(me.quit)
|
||||||
@ -622,12 +623,7 @@ func (cl *Client) acceptConnections(l net.Listener, utp bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (me *Client) torrent(ih InfoHash) *torrent {
|
func (me *Client) torrent(ih InfoHash) *torrent {
|
||||||
for _, t := range me.torrents {
|
return me.torrents[ih]
|
||||||
if t.InfoHash == ih {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type dialResult struct {
|
type dialResult struct {
|
||||||
@ -1342,7 +1338,8 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
err := me.AddPeers(t.InfoHash, func() (ret []Peer) {
|
me.mu.Lock()
|
||||||
|
me.addPeers(t, func() (ret []Peer) {
|
||||||
for _, cp := range pexMsg.Added {
|
for _, cp := range pexMsg.Added {
|
||||||
p := Peer{
|
p := Peer{
|
||||||
IP: make([]byte, 4),
|
IP: make([]byte, 4),
|
||||||
@ -1356,10 +1353,7 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}())
|
}())
|
||||||
if err != nil {
|
me.mu.Unlock()
|
||||||
log.Printf("error adding PEX peers: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
peersFoundByPEX.Add(int64(len(pexMsg.Added)))
|
peersFoundByPEX.Add(int64(len(pexMsg.Added)))
|
||||||
}()
|
}()
|
||||||
default:
|
default:
|
||||||
@ -1513,34 +1507,19 @@ func (me *Client) openNewConns(t *torrent) {
|
|||||||
|
|
||||||
func (me *Client) addPeers(t *torrent, peers []Peer) {
|
func (me *Client) addPeers(t *torrent, peers []Peer) {
|
||||||
blocked := 0
|
blocked := 0
|
||||||
for i, p := range peers {
|
for _, p := range peers {
|
||||||
if me.ipBlockRange(p.IP) == nil {
|
if me.ipBlockRange(p.IP) != nil {
|
||||||
|
blocked++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
peers[i] = peers[len(peers)-1]
|
t.addPeer(p)
|
||||||
peers = peers[:len(peers)-1]
|
|
||||||
i--
|
|
||||||
blocked++
|
|
||||||
}
|
}
|
||||||
if blocked != 0 {
|
if blocked != 0 {
|
||||||
log.Printf("IP blocklist screened %d peers from being added", blocked)
|
log.Printf("IP blocklist screened %d peers from being added", blocked)
|
||||||
}
|
}
|
||||||
t.AddPeers(peers)
|
|
||||||
me.openNewConns(t)
|
me.openNewConns(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds peers to the swarm for the torrent corresponding to infoHash.
|
|
||||||
func (me *Client) AddPeers(infoHash InfoHash, peers []Peer) error {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
t := me.torrent(infoHash)
|
|
||||||
if t == nil {
|
|
||||||
return errors.New("no such torrent")
|
|
||||||
}
|
|
||||||
me.addPeers(t, peers)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cl *Client) torrentFileCachePath(ih InfoHash) string {
|
func (cl *Client) torrentFileCachePath(ih InfoHash) string {
|
||||||
return filepath.Join(cl.configDir(), "torrents", ih.HexString()+".torrent")
|
return filepath.Join(cl.configDir(), "torrents", ih.HexString()+".torrent")
|
||||||
}
|
}
|
||||||
@ -1592,7 +1571,7 @@ func (cl *Client) startTorrent(t *torrent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Storage cannot be changed once it's set.
|
// Storage cannot be changed once it's set.
|
||||||
func (cl *Client) setStorage(t *torrent, td Data) (err error) {
|
func (cl *Client) setStorage(t *torrent, td data.Data) (err error) {
|
||||||
err = t.setStorage(td)
|
err = t.setStorage(td)
|
||||||
cl.event.Broadcast()
|
cl.event.Broadcast()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1881,7 +1860,11 @@ func (t Torrent) MetainfoFilepath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t Torrent) AddPeers(pp []Peer) error {
|
func (t Torrent) AddPeers(pp []Peer) error {
|
||||||
return t.cl.AddPeers(t.torrent.InfoHash, pp)
|
cl := t.cl
|
||||||
|
cl.mu.Lock()
|
||||||
|
defer cl.mu.Unlock()
|
||||||
|
cl.addPeers(t.torrent, pp)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Torrent) DownloadAll() {
|
func (t Torrent) DownloadAll() {
|
||||||
@ -2142,12 +2125,10 @@ func (cl *Client) announceTorrentSingleTracker(tr tracker.Client, req *tracker.A
|
|||||||
Port: peer.Port,
|
Port: peer.Port,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
err = cl.AddPeers(t.InfoHash, peers)
|
cl.mu.Lock()
|
||||||
if err != nil {
|
cl.addPeers(t, peers)
|
||||||
log.Printf("error adding peers to torrent %s: %s", t, err)
|
cl.mu.Unlock()
|
||||||
} else {
|
|
||||||
log.Printf("%s: %d new peers from %s", t, len(peers), tr)
|
log.Printf("%s: %d new peers from %s", t, len(peers), tr)
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(time.Second * time.Duration(resp.Interval))
|
time.Sleep(time.Second * time.Duration(resp.Interval))
|
||||||
return nil
|
return nil
|
||||||
@ -2393,14 +2374,7 @@ func (cl *Client) verifyPiece(t *torrent, index pp.Integer) {
|
|||||||
cl.pieceHashed(t, index, sum == p.Hash)
|
cl.pieceHashed(t, index, sum == p.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) Torrent(ih InfoHash) (t Torrent, ok bool) {
|
// Returns handles to all the torrents loaded in the Client.
|
||||||
cl.mu.Lock()
|
|
||||||
defer cl.mu.Unlock()
|
|
||||||
t.torrent, ok = cl.torrents[ih]
|
|
||||||
t.cl = cl
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Client) Torrents() (ret []Torrent) {
|
func (me *Client) Torrents() (ret []Torrent) {
|
||||||
me.mu.Lock()
|
me.mu.Lock()
|
||||||
for _, t := range me.torrents {
|
for _, t := range me.torrents {
|
||||||
|
@ -37,7 +37,7 @@ func TestClientDefault(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
cl.Stop()
|
cl.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDropTorrent(t *testing.T) {
|
func TestAddDropTorrent(t *testing.T) {
|
||||||
@ -47,7 +47,7 @@ func TestAddDropTorrent(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer cl.Stop()
|
defer cl.Close()
|
||||||
dir, mi := testutil.GreetingTestTorrent()
|
dir, mi := testutil.GreetingTestTorrent()
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
tt, err := cl.AddTorrent(mi)
|
tt, err := cl.AddTorrent(mi)
|
||||||
@ -223,13 +223,13 @@ func TestTwoClientsArbitraryPorts(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer cl.Stop()
|
defer cl.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDropManyTorrents(t *testing.T) {
|
func TestAddDropManyTorrents(t *testing.T) {
|
||||||
cl, _ := NewClient(&TestingConfig)
|
cl, _ := NewClient(&TestingConfig)
|
||||||
defer cl.Stop()
|
defer cl.Close()
|
||||||
var m Magnet
|
var m Magnet
|
||||||
for i := range iter.N(1000) {
|
for i := range iter.N(1000) {
|
||||||
binary.PutVarint(m.InfoHash[:], int64(i))
|
binary.PutVarint(m.InfoHash[:], int64(i))
|
||||||
@ -246,7 +246,7 @@ func TestClientTransfer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer seeder.Stop()
|
defer seeder.Close()
|
||||||
seeder.AddTorrent(mi)
|
seeder.AddTorrent(mi)
|
||||||
leecherDataDir, err := ioutil.TempDir("", "")
|
leecherDataDir, err := ioutil.TempDir("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -258,7 +258,7 @@ func TestClientTransfer(t *testing.T) {
|
|||||||
// }
|
// }
|
||||||
cfg.TorrentDataOpener = blob.NewStore(leecherDataDir).OpenTorrent
|
cfg.TorrentDataOpener = blob.NewStore(leecherDataDir).OpenTorrent
|
||||||
leecher, _ := NewClient(&cfg)
|
leecher, _ := NewClient(&cfg)
|
||||||
defer leecher.Stop()
|
defer leecher.Close()
|
||||||
leecherGreeting, _ := leecher.AddTorrent(mi)
|
leecherGreeting, _ := leecher.AddTorrent(mi)
|
||||||
leecherGreeting.AddPeers([]Peer{
|
leecherGreeting.AddPeers([]Peer{
|
||||||
Peer{
|
Peer{
|
||||||
|
@ -42,7 +42,7 @@ func main() {
|
|||||||
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
|
||||||
client.WriteStatus(w)
|
client.WriteStatus(w)
|
||||||
})
|
})
|
||||||
defer client.Stop()
|
defer client.Close()
|
||||||
if flag.NArg() == 0 {
|
if flag.NArg() == 0 {
|
||||||
fmt.Fprintln(os.Stderr, "no torrents specified")
|
fmt.Fprintln(os.Stderr, "no torrents specified")
|
||||||
return
|
return
|
||||||
|
@ -69,7 +69,7 @@ func exitSignalHandlers(fs *torrentfs.TorrentFS) {
|
|||||||
func addTestPeer(client *torrent.Client) {
|
func addTestPeer(client *torrent.Client) {
|
||||||
for _, t := range client.Torrents() {
|
for _, t := range client.Torrents() {
|
||||||
if testPeerAddr != nil {
|
if testPeerAddr != nil {
|
||||||
if err := client.AddPeers(t.InfoHash, []torrent.Peer{{
|
if err := t.AddPeers([]torrent.Peer{{
|
||||||
IP: testPeerAddr.IP,
|
IP: testPeerAddr.IP,
|
||||||
Port: testPeerAddr.Port,
|
Port: testPeerAddr.Port,
|
||||||
}}); err != nil {
|
}}); err != nil {
|
||||||
|
22
config.go
22
config.go
@ -4,20 +4,38 @@ import (
|
|||||||
"bitbucket.org/anacrolix/go.torrent/dht"
|
"bitbucket.org/anacrolix/go.torrent/dht"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Override Client defaults.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// Store torrent file data in this directory unless TorrentDataOpener is
|
||||||
|
// specified.
|
||||||
DataDir string
|
DataDir string
|
||||||
|
// The address to listen for new uTP and TCP bittorrent protocol
|
||||||
|
// connections. DHT shares a UDP socket with uTP unless configured
|
||||||
|
// otherwise.
|
||||||
ListenAddr string
|
ListenAddr string
|
||||||
|
// Don't announce to trackers. This only leaves DHT to discover peers.
|
||||||
DisableTrackers bool
|
DisableTrackers bool
|
||||||
DownloadStrategy DownloadStrategy
|
// Don't create a DHT.
|
||||||
NoDHT bool
|
NoDHT bool
|
||||||
|
// Overrides the default DHT configuration.
|
||||||
DHTConfig *dht.ServerConfig
|
DHTConfig *dht.ServerConfig
|
||||||
|
// Don't chunks to peers.
|
||||||
NoUpload bool
|
NoUpload bool
|
||||||
|
// User-provided Client peer ID. If not present, one is generated automatically.
|
||||||
PeerID string
|
PeerID string
|
||||||
|
// For the bittorrent protocol.
|
||||||
DisableUTP bool
|
DisableUTP bool
|
||||||
|
// For the bittorrent protocol.
|
||||||
DisableTCP bool
|
DisableTCP bool
|
||||||
|
// Don't automatically load "$ConfigDir/blocklist".
|
||||||
NoDefaultBlocklist bool
|
NoDefaultBlocklist bool
|
||||||
// Defaults to "$HOME/.config/torrent"
|
// Defaults to "$HOME/.config/torrent". This is where "blocklist",
|
||||||
|
// "torrents" and other operational files are stored.
|
||||||
ConfigDir string
|
ConfigDir string
|
||||||
|
// Don't save or load to a cache of torrent files stored in
|
||||||
|
// "$ConfigDir/torrents".
|
||||||
DisableMetainfoCache bool
|
DisableMetainfoCache bool
|
||||||
|
// Called to instantiate storage for each added torrent. Provided backends
|
||||||
|
// are in $REPO/data. If not set, the "file" implementation is used.
|
||||||
TorrentDataOpener
|
TorrentDataOpener
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ type Store interface {
|
|||||||
OpenTorrent(*metainfo.Info) Data
|
OpenTorrent(*metainfo.Info) Data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents data storage for a Torrent. Additional optional interfaces to
|
||||||
|
// implement are io.Closer, io.ReaderAt, StatefulData, and SectionOpener.
|
||||||
type Data interface {
|
type Data interface {
|
||||||
// OpenSection(off, n int64) (io.ReadCloser, error)
|
// OpenSection(off, n int64) (io.ReadCloser, error)
|
||||||
// ReadAt(p []byte, off int64) (n int, err error)
|
// ReadAt(p []byte, off int64) (n int, err error)
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
pp "bitbucket.org/anacrolix/go.torrent/peer_protocol"
|
pp "bitbucket.org/anacrolix/go.torrent/peer_protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DownloadStrategy interface {
|
type downloadStrategy interface {
|
||||||
// Tops up the outgoing pending requests.
|
// Tops up the outgoing pending requests.
|
||||||
FillRequests(*torrent, *connection)
|
FillRequests(*torrent, *connection)
|
||||||
TorrentStarted(*torrent)
|
TorrentStarted(*torrent)
|
||||||
@ -20,17 +20,17 @@ type DownloadStrategy interface {
|
|||||||
PendingData(*torrent) bool
|
PendingData(*torrent) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultDownloadStrategy struct{}
|
type defaultDownloadStrategy struct{}
|
||||||
|
|
||||||
func (me *DefaultDownloadStrategy) PendingData(t *torrent) bool {
|
func (me *defaultDownloadStrategy) PendingData(t *torrent) bool {
|
||||||
return !t.haveAllPieces()
|
return !t.haveAllPieces()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *DefaultDownloadStrategy) AssertNotRequested(t *torrent, r request) {}
|
func (me *defaultDownloadStrategy) AssertNotRequested(t *torrent, r request) {}
|
||||||
|
|
||||||
func (me *DefaultDownloadStrategy) WriteStatus(w io.Writer) {}
|
func (me *defaultDownloadStrategy) WriteStatus(w io.Writer) {}
|
||||||
|
|
||||||
func (s *DefaultDownloadStrategy) FillRequests(t *torrent, c *connection) {
|
func (s *defaultDownloadStrategy) FillRequests(t *torrent, c *connection) {
|
||||||
if c.Interested {
|
if c.Interested {
|
||||||
if c.PeerChoked {
|
if c.PeerChoked {
|
||||||
return
|
return
|
||||||
@ -64,14 +64,14 @@ func (s *DefaultDownloadStrategy) FillRequests(t *torrent, c *connection) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultDownloadStrategy) TorrentStarted(t *torrent) {}
|
func (s *defaultDownloadStrategy) TorrentStarted(t *torrent) {}
|
||||||
|
|
||||||
func (s *DefaultDownloadStrategy) TorrentStopped(t *torrent) {
|
func (s *defaultDownloadStrategy) TorrentStopped(t *torrent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultDownloadStrategy) DeleteRequest(t *torrent, r request) {
|
func (s *defaultDownloadStrategy) DeleteRequest(t *torrent, r request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *DefaultDownloadStrategy) TorrentGotChunk(t *torrent, c request) {}
|
func (me *defaultDownloadStrategy) TorrentGotChunk(t *torrent, c request) {}
|
||||||
func (me *DefaultDownloadStrategy) TorrentGotPiece(t *torrent, piece int) {}
|
func (me *defaultDownloadStrategy) TorrentGotPiece(t *torrent, piece int) {}
|
||||||
func (*DefaultDownloadStrategy) TorrentPrioritize(t *torrent, off, _len int64) {}
|
func (*defaultDownloadStrategy) TorrentPrioritize(t *torrent, off, _len int64) {}
|
||||||
|
@ -98,7 +98,7 @@ func TestUnmountWedged(t *testing.T) {
|
|||||||
|
|
||||||
NoDefaultBlocklist: true,
|
NoDefaultBlocklist: true,
|
||||||
})
|
})
|
||||||
defer client.Stop()
|
defer client.Close()
|
||||||
client.AddTorrent(layout.Metainfo)
|
client.AddTorrent(layout.Metainfo)
|
||||||
fs := New(client)
|
fs := New(client)
|
||||||
fuseConn, err := fuse.Mount(layout.MountDir)
|
fuseConn, err := fuse.Mount(layout.MountDir)
|
||||||
@ -177,7 +177,7 @@ func TestDownloadOnDemand(t *testing.T) {
|
|||||||
t.Fatalf("error creating seeder client: %s", err)
|
t.Fatalf("error creating seeder client: %s", err)
|
||||||
}
|
}
|
||||||
seeder.SetIPBlockList(nil)
|
seeder.SetIPBlockList(nil)
|
||||||
defer seeder.Stop()
|
defer seeder.Close()
|
||||||
http.HandleFunc("/seeder", func(w http.ResponseWriter, req *http.Request) {
|
http.HandleFunc("/seeder", func(w http.ResponseWriter, req *http.Request) {
|
||||||
seeder.WriteStatus(w)
|
seeder.WriteStatus(w)
|
||||||
})
|
})
|
||||||
@ -207,11 +207,9 @@ func TestDownloadOnDemand(t *testing.T) {
|
|||||||
http.HandleFunc("/leecher", func(w http.ResponseWriter, req *http.Request) {
|
http.HandleFunc("/leecher", func(w http.ResponseWriter, req *http.Request) {
|
||||||
leecher.WriteStatus(w)
|
leecher.WriteStatus(w)
|
||||||
})
|
})
|
||||||
defer leecher.Stop()
|
defer leecher.Close()
|
||||||
leecher.AddTorrent(layout.Metainfo)
|
leecherTorrent, _ := leecher.AddTorrent(layout.Metainfo)
|
||||||
var ih torrent.InfoHash
|
leecherTorrent.AddPeers([]torrent.Peer{func() torrent.Peer {
|
||||||
util.CopyExact(ih[:], layout.Metainfo.Info.Hash)
|
|
||||||
leecher.AddPeers(ih, []torrent.Peer{func() torrent.Peer {
|
|
||||||
_, port, err := net.SplitHostPort(seeder.ListenAddr().String())
|
_, port, err := net.SplitHostPort(seeder.ListenAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -21,8 +21,9 @@ func (r *Range) String() string {
|
|||||||
return fmt.Sprintf("%s-%s (%s)", r.First, r.Last, r.Description)
|
return fmt.Sprintf("%s-%s (%s)", r.First, r.Last, r.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new IP list. The given range must already sorted by the lower IP
|
// Create a new IP list. The given ranges must already sorted by the lower
|
||||||
// in the range. Behaviour is undefined for lists of overlapping ranges.
|
// bound IP in each range. Behaviour is undefined for lists of overlapping
|
||||||
|
// ranges.
|
||||||
func New(initSorted []Range) *IPList {
|
func New(initSorted []Range) *IPList {
|
||||||
return &IPList{
|
return &IPList{
|
||||||
ranges: initSorted,
|
ranges: initSorted,
|
||||||
|
4
misc.go
4
misc.go
@ -15,7 +15,7 @@ const (
|
|||||||
pieceHash = crypto.SHA1
|
pieceHash = crypto.SHA1
|
||||||
maxRequests = 250 // Maximum pending requests we allow peers to send us.
|
maxRequests = 250 // Maximum pending requests we allow peers to send us.
|
||||||
chunkSize = 0x4000 // 16KiB
|
chunkSize = 0x4000 // 16KiB
|
||||||
BEP20 = "-GT0000-" // Peer ID client identifier prefix
|
bep20 = "-GT0000-" // Peer ID client identifier prefix
|
||||||
nominalDialTimeout = time.Second * 30
|
nominalDialTimeout = time.Second * 30
|
||||||
minDialTimeout = 5 * time.Second
|
minDialTimeout = 5 * time.Second
|
||||||
)
|
)
|
||||||
@ -97,7 +97,7 @@ func newRequest(index, begin, length peer_protocol.Integer) request {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// Requested data not yet available.
|
// Requested data not yet available.
|
||||||
ErrDataNotReady = errors.New("data not ready")
|
errDataNotReady = errors.New("data not ready")
|
||||||
)
|
)
|
||||||
|
|
||||||
// The size in bytes of a metadata extension piece.
|
// The size in bytes of a metadata extension piece.
|
||||||
|
19
ordered.go
19
ordered.go
@ -4,23 +4,26 @@ import (
|
|||||||
"container/list"
|
"container/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrderedList struct {
|
// This was used to maintain pieces in order of bytes left to download. I
|
||||||
|
// don't think it's currently in use.
|
||||||
|
|
||||||
|
type orderedList struct {
|
||||||
list *list.List
|
list *list.List
|
||||||
lessFunc func(a, b interface{}) bool
|
lessFunc func(a, b interface{}) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *OrderedList) Len() int {
|
func (me *orderedList) Len() int {
|
||||||
return me.list.Len()
|
return me.list.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewList(lessFunc func(a, b interface{}) bool) *OrderedList {
|
func newOrderedList(lessFunc func(a, b interface{}) bool) *orderedList {
|
||||||
return &OrderedList{
|
return &orderedList{
|
||||||
list: list.New(),
|
list: list.New(),
|
||||||
lessFunc: lessFunc,
|
lessFunc: lessFunc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *OrderedList) ValueChanged(e *list.Element) {
|
func (me *orderedList) ValueChanged(e *list.Element) {
|
||||||
for prev := e.Prev(); prev != nil && me.lessFunc(e.Value, prev.Value); prev = e.Prev() {
|
for prev := e.Prev(); prev != nil && me.lessFunc(e.Value, prev.Value); prev = e.Prev() {
|
||||||
me.list.MoveBefore(e, prev)
|
me.list.MoveBefore(e, prev)
|
||||||
}
|
}
|
||||||
@ -29,16 +32,16 @@ func (me *OrderedList) ValueChanged(e *list.Element) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *OrderedList) Insert(value interface{}) (ret *list.Element) {
|
func (me *orderedList) Insert(value interface{}) (ret *list.Element) {
|
||||||
ret = me.list.PushFront(value)
|
ret = me.list.PushFront(value)
|
||||||
me.ValueChanged(ret)
|
me.ValueChanged(ret)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *OrderedList) Front() *list.Element {
|
func (me *orderedList) Front() *list.Element {
|
||||||
return me.list.Front()
|
return me.list.Front()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *OrderedList) Remove(e *list.Element) interface{} {
|
func (me *orderedList) Remove(e *list.Element) interface{} {
|
||||||
return me.list.Remove(e)
|
return me.list.Remove(e)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestOrderedList(t *testing.T) {
|
func TestOrderedList(t *testing.T) {
|
||||||
ol := NewList(func(a, b interface{}) bool {
|
ol := newOrderedList(func(a, b interface{}) bool {
|
||||||
return a.(int) < b.(int)
|
return a.(int) < b.(int)
|
||||||
})
|
})
|
||||||
if ol.Len() != 0 {
|
if ol.Len() != 0 {
|
||||||
|
18
torrent.go
18
torrent.go
@ -44,15 +44,9 @@ type peersKey struct {
|
|||||||
Port int
|
Port int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents data storage for a Torrent. Additional optional interfaces to
|
|
||||||
// implement are io.Closer, io.ReaderAt, StatefulData, and SectionOpener.
|
|
||||||
type Data interface {
|
|
||||||
data.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
// Data maintains per-piece persistent state.
|
// Data maintains per-piece persistent state.
|
||||||
type StatefulData interface {
|
type StatefulData interface {
|
||||||
Data
|
data.Data
|
||||||
// We believe the piece data will pass a hash check.
|
// We believe the piece data will pass a hash check.
|
||||||
PieceCompleted(index int) error
|
PieceCompleted(index int) error
|
||||||
// Returns true if the piece is complete.
|
// Returns true if the piece is complete.
|
||||||
@ -72,7 +66,7 @@ type torrent struct {
|
|||||||
Pieces []*piece
|
Pieces []*piece
|
||||||
length int64
|
length int64
|
||||||
|
|
||||||
data Data
|
data data.Data
|
||||||
|
|
||||||
Info *metainfo.Info
|
Info *metainfo.Info
|
||||||
// Active peer connections.
|
// Active peer connections.
|
||||||
@ -229,11 +223,9 @@ func (t *torrent) ceaseNetworking() {
|
|||||||
t.pruneTimer.Stop()
|
t.pruneTimer.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *torrent) AddPeers(pp []Peer) {
|
func (t *torrent) addPeer(p Peer) {
|
||||||
for _, p := range pp {
|
|
||||||
t.Peers[peersKey{string(p.IP), p.Port}] = p
|
t.Peers[peersKey{string(p.IP), p.Port}] = p
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (t *torrent) invalidateMetadata() {
|
func (t *torrent) invalidateMetadata() {
|
||||||
t.MetaData = nil
|
t.MetaData = nil
|
||||||
@ -305,7 +297,7 @@ func (t *torrent) setMetadata(md metainfo.Info, infoBytes []byte, eventLocker sy
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *torrent) setStorage(td Data) (err error) {
|
func (t *torrent) setStorage(td data.Data) (err error) {
|
||||||
if c, ok := t.data.(io.Closer); ok {
|
if c, ok := t.data.(io.Closer); ok {
|
||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
@ -539,7 +531,7 @@ func (t *torrent) piecePartiallyDownloaded(index int) bool {
|
|||||||
return t.PieceNumPendingBytes(pp.Integer(index)) != t.PieceLength(pp.Integer(index))
|
return t.PieceNumPendingBytes(pp.Integer(index)) != t.PieceLength(pp.Integer(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NumChunksForPiece(chunkSize int, pieceSize int) int {
|
func numChunksForPiece(chunkSize int, pieceSize int) int {
|
||||||
return (pieceSize + chunkSize - 1) / chunkSize
|
return (pieceSize + chunkSize - 1) / chunkSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user