init 1.2.x

This commit is contained in:
YouROK
2020-11-06 15:40:58 +03:00
parent ce87ecabcb
commit a1e17b1cf3
57 changed files with 670 additions and 4003 deletions

View File

@@ -1,185 +0,0 @@
package torr
import (
"fmt"
"io"
"sync"
"server/settings"
"server/torr/storage/memcache"
"server/torr/storage/state"
"server/utils"
"log"
"github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/metainfo"
)
type BTServer struct {
config *torrent.ClientConfig
client *torrent.Client
storage *memcache.Storage
torrents map[metainfo.Hash]*Torrent
mu sync.Mutex
wmu sync.Mutex
watching bool
}
func NewBTS() *BTServer {
bts := new(BTServer)
bts.torrents = make(map[metainfo.Hash]*Torrent)
return bts
}
func (bt *BTServer) Connect() error {
bt.mu.Lock()
defer bt.mu.Unlock()
var err error
bt.configure()
bt.client, err = torrent.NewClient(bt.config)
bt.torrents = make(map[metainfo.Hash]*Torrent)
return err
}
func (bt *BTServer) Disconnect() {
bt.mu.Lock()
defer bt.mu.Unlock()
if bt.client != nil {
bt.client.Close()
bt.client = nil
utils.FreeOSMemGC()
}
}
func (bt *BTServer) Reconnect() error {
bt.Disconnect()
return bt.Connect()
}
func (bt *BTServer) configure() {
bt.storage = memcache.NewStorage(settings.Get().CacheSize)
//blocklist, _ := iplist.MMapPackedFile(filepath.Join(settings.Path, "blocklist"))
blocklist, _ := utils.ReadBlockedIP()
userAgent := "uTorrent/3.5.5"
peerID := "-UT3550-"
cliVers := "µTorrent 3.5.5"
bt.config = torrent.NewDefaultClientConfig()
bt.config.Debug = settings.Get().EnableDebug
bt.config.DisableIPv6 = settings.Get().EnableIPv6 == false
bt.config.DisableTCP = settings.Get().DisableTCP
bt.config.DisableUTP = settings.Get().DisableUTP
bt.config.NoDefaultPortForwarding = settings.Get().DisableUPNP
bt.config.NoDHT = settings.Get().DisableDHT
bt.config.NoUpload = settings.Get().DisableUpload
bt.config.EncryptionPolicy = torrent.EncryptionPolicy{
DisableEncryption: settings.Get().Encryption == 1,
ForceEncryption: settings.Get().Encryption == 2,
}
bt.config.IPBlocklist = blocklist
bt.config.DefaultStorage = bt.storage
bt.config.Bep20 = peerID
bt.config.PeerID = utils.PeerIDRandom(peerID)
bt.config.HTTPUserAgent = userAgent
bt.config.ExtendedHandshakeClientVersion = cliVers
bt.config.EstablishedConnsPerTorrent = settings.Get().ConnectionsLimit
if settings.Get().DhtConnectionLimit > 0 {
bt.config.ConnTracker.SetMaxEntries(settings.Get().DhtConnectionLimit)
}
if settings.Get().DownloadRateLimit > 0 {
bt.config.DownloadRateLimiter = utils.Limit(settings.Get().DownloadRateLimit * 1024)
}
if settings.Get().UploadRateLimit > 0 {
bt.config.UploadRateLimiter = utils.Limit(settings.Get().UploadRateLimit * 1024)
}
if settings.Get().PeersListenPort > 0 {
bt.config.ListenPort = settings.Get().PeersListenPort
}
log.Println("Configure client:", settings.Get())
}
func (bt *BTServer) AddTorrent(magnet metainfo.Magnet, infobytes []byte, onAdd func(*Torrent)) (*Torrent, error) {
torr, err := NewTorrent(magnet, infobytes, bt)
if err != nil {
return nil, err
}
if onAdd != nil {
go func() {
if torr.GotInfo() {
onAdd(torr)
}
}()
} else {
go torr.GotInfo()
}
return torr, nil
}
func (bt *BTServer) List() []*Torrent {
bt.mu.Lock()
defer bt.mu.Unlock()
list := make([]*Torrent, 0)
for _, t := range bt.torrents {
list = append(list, t)
}
return list
}
func (bt *BTServer) GetTorrent(hash metainfo.Hash) *Torrent {
bt.mu.Lock()
defer bt.mu.Unlock()
if t, ok := bt.torrents[hash]; ok {
return t
}
return nil
}
func (bt *BTServer) RemoveTorrent(hash torrent.InfoHash) {
if torr, ok := bt.torrents[hash]; ok {
torr.Close()
}
}
func (bt *BTServer) BTState() *BTState {
bt.mu.Lock()
defer bt.mu.Unlock()
btState := new(BTState)
btState.LocalPort = bt.client.LocalPort()
btState.PeerID = fmt.Sprintf("%x", bt.client.PeerID())
btState.BannedIPs = len(bt.client.BadPeerIPs())
for _, dht := range bt.client.DhtServers() {
btState.DHTs = append(btState.DHTs, dht)
}
for _, t := range bt.torrents {
btState.Torrents = append(btState.Torrents, t)
}
return btState
}
func (bt *BTServer) CacheState(hash metainfo.Hash) *state.CacheState {
st := bt.GetTorrent(hash)
if st == nil {
return nil
}
cacheState := bt.storage.GetStats(hash)
return cacheState
}
func (bt *BTServer) WriteState(w io.Writer) {
bt.client.WriteStatus(w)
}

View File

@@ -1,51 +0,0 @@
package torr
import (
"fmt"
"net/http"
"time"
"server/settings"
"server/utils"
"log"
"github.com/anacrolix/missinggo/httptoo"
"github.com/anacrolix/torrent"
"github.com/labstack/echo"
)
func (bt *BTServer) View(torr *Torrent, file *torrent.File, c echo.Context) error {
go settings.SetViewed(torr.Hash().HexString(), file.Path())
reader := torr.NewReader(file, 0)
log.Println("Connect client")
c.Response().Header().Set("Connection", "close")
c.Response().Header().Set("ETag", httptoo.EncodeQuotedString(fmt.Sprintf("%s/%s", torr.Hash().HexString(), file.Path())))
http.ServeContent(c.Response(), c.Request(), file.Path(), time.Time{}, reader)
log.Println("Disconnect client")
torr.CloseReader(reader)
return c.NoContent(http.StatusOK)
}
func (bt *BTServer) Play(torr *Torrent, file *torrent.File, preload int64, c echo.Context) error {
if torr.status == TorrentAdded {
if !torr.GotInfo() {
return echo.NewHTTPError(http.StatusBadRequest, "torrent closed befor get info")
}
}
if torr.status == TorrentGettingInfo {
if !torr.WaitInfo() {
return echo.NewHTTPError(http.StatusBadRequest, "torrent closed befor get info")
}
}
if torr.PreloadedBytes == 0 {
torr.Preload(file, preload)
}
redirectUrl := c.Scheme() + "://" + c.Request().Host + "/torrent/view/" + torr.Hash().HexString() + "/" + utils.CleanFName(file.Path())
return c.Redirect(http.StatusFound, redirectUrl)
}

View File

@@ -1,57 +0,0 @@
package torr
import (
"github.com/anacrolix/dht"
)
type BTState struct {
LocalPort int
PeerID string
BannedIPs int
DHTs []*dht.Server
Torrents []*Torrent
}
type TorrentStats struct {
Name string
Hash string
TorrentStatus TorrentStatus
TorrentStatusString string
LoadedSize int64
TorrentSize int64
PreloadedBytes int64
PreloadSize int64
DownloadSpeed float64
UploadSpeed float64
TotalPeers int
PendingPeers int
ActivePeers int
ConnectedSeeders int
HalfOpenPeers int
BytesWritten int64
BytesWrittenData int64
BytesRead int64
BytesReadData int64
BytesReadUsefulData int64
ChunksWritten int64
ChunksRead int64
ChunksReadUseful int64
ChunksReadWasted int64
PiecesDirtiedGood int64
PiecesDirtiedBad int64
FileStats []TorrentFileStat
}
type TorrentFileStat struct {
Id int
Path string
Length int64
}

106
src/server/torr/btserver.go Normal file
View File

@@ -0,0 +1,106 @@
package torr
import (
"log"
"sync"
"server/settings"
"server/torr/storage/torrstor"
"server/torr/utils"
"github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/metainfo"
)
type BTServer struct {
config *torrent.ClientConfig
client *torrent.Client
storage *torrstor.Storage
torrents map[metainfo.Hash]*Torrent
mu sync.Mutex
}
func NewBTS() *BTServer {
bts := new(BTServer)
bts.torrents = make(map[metainfo.Hash]*Torrent)
return bts
}
func (bt *BTServer) Connect() error {
bt.mu.Lock()
defer bt.mu.Unlock()
var err error
bt.configure()
bt.client, err = torrent.NewClient(bt.config)
bt.torrents = make(map[metainfo.Hash]*Torrent)
return err
}
func (bt *BTServer) Disconnect() {
bt.mu.Lock()
defer bt.mu.Unlock()
if bt.client != nil {
bt.client.Close()
bt.client = nil
utils.FreeOSMemGC()
}
}
func (bt *BTServer) Reconnect() error {
bt.Disconnect()
return bt.Connect()
}
func (bt *BTServer) configure() {
bt.storage = torrstor.NewStorage(settings.BTsets.CacheSize)
blocklist, _ := utils.ReadBlockedIP()
userAgent := "uTorrent/3.5.5"
peerID := "-UT3550-"
cliVers := "µTorrent 3.5.5"
bt.config = torrent.NewDefaultClientConfig()
bt.config.Debug = settings.BTsets.EnableDebug
bt.config.DisableIPv6 = settings.BTsets.EnableIPv6 == false
bt.config.DisableTCP = settings.BTsets.DisableTCP
bt.config.DisableUTP = settings.BTsets.DisableUTP
bt.config.NoDefaultPortForwarding = settings.BTsets.DisableUPNP
bt.config.NoDHT = settings.BTsets.DisableDHT
bt.config.NoUpload = settings.BTsets.DisableUpload
// bt.config.EncryptionPolicy = torrent.EncryptionPolicy{
// DisableEncryption: settings.BTsets.Encryption == 1,
// ForceEncryption: settings.BTsets.Encryption == 2,
// }
bt.config.IPBlocklist = blocklist
bt.config.DefaultStorage = bt.storage
bt.config.Bep20 = peerID
bt.config.PeerID = utils.PeerIDRandom(peerID)
bt.config.HTTPUserAgent = userAgent
bt.config.ExtendedHandshakeClientVersion = cliVers
bt.config.EstablishedConnsPerTorrent = settings.BTsets.ConnectionsLimit
if settings.BTsets.DhtConnectionLimit > 0 {
bt.config.ConnTracker.SetMaxEntries(settings.BTsets.DhtConnectionLimit)
}
if settings.BTsets.DownloadRateLimit > 0 {
bt.config.DownloadRateLimiter = utils.Limit(settings.BTsets.DownloadRateLimit * 1024)
}
if settings.BTsets.UploadRateLimit > 0 {
bt.config.UploadRateLimiter = utils.Limit(settings.BTsets.UploadRateLimit * 1024)
}
if settings.BTsets.PeersListenPort > 0 {
bt.config.ListenPort = settings.BTsets.PeersListenPort
}
log.Println("Configure client:", settings.BTsets)
}
func (bt *BTServer) RemoveTorrent(hash torrent.InfoHash) {
if torr, ok := bt.torrents[hash]; ok {
torr.Close()
}
}

View File

@@ -2,6 +2,8 @@ package reader
import (
"github.com/anacrolix/torrent"
"server/torr"
"io"
)
@@ -12,10 +14,16 @@ type Reader struct {
file *torrent.File
}
func NewReader(file *torrent.File) *Reader {
func NewReader(torr *torr.Torrent, file *torrent.File, readahead int64) *Reader {
r := new(Reader)
r.file = file
r.Reader = file.NewReader()
if readahead <= 0 {
readahead = torr.Torrent.Info().PieceLength
}
r.SetReadahead(readahead)
torr.GetCache().AddReader(r)
return r
}

130
src/server/torr/state.go Normal file
View File

@@ -0,0 +1,130 @@
package torr
import (
"fmt"
"sort"
"github.com/anacrolix/torrent"
)
type BTState struct {
LocalPort int
PeerID string
BannedIPs int
DHTs []torrent.DhtServer
Torrents []*Torrent
}
func (bt *BTServer) BTState() *BTState {
bt.mu.Lock()
defer bt.mu.Unlock()
btState := new(BTState)
btState.LocalPort = bt.client.LocalPort()
btState.PeerID = fmt.Sprintf("%x", bt.client.PeerID())
btState.BannedIPs = len(bt.client.BadPeerIPs())
btState.DHTs = bt.client.DhtServers()
for _, t := range bt.torrents {
btState.Torrents = append(btState.Torrents, t)
}
return btState
}
type TorrentStats struct {
Name string
Hash string
TorrentStatus TorrentStatus
TorrentStatusString string
LoadedSize int64
TorrentSize int64
PreloadedBytes int64
PreloadSize int64
DownloadSpeed float64
UploadSpeed float64
TotalPeers int
PendingPeers int
ActivePeers int
ConnectedSeeders int
HalfOpenPeers int
BytesWritten int64
BytesWrittenData int64
BytesRead int64
BytesReadData int64
BytesReadUsefulData int64
ChunksWritten int64
ChunksRead int64
ChunksReadUseful int64
ChunksReadWasted int64
PiecesDirtiedGood int64
PiecesDirtiedBad int64
FileStats []TorrentFileStat
}
type TorrentFileStat struct {
Id int
Path string
Length int64
}
func (t *Torrent) Stats() TorrentStats {
t.muTorrent.Lock()
defer t.muTorrent.Unlock()
st := TorrentStats{}
st.Name = t.Name()
st.Hash = t.hash.HexString()
st.TorrentStatus = t.status
st.TorrentStatusString = t.status.String()
if t.Torrent != nil {
st.LoadedSize = t.Torrent.BytesCompleted()
st.TorrentSize = t.Length()
st.PreloadedBytes = t.PreloadedBytes
st.PreloadSize = t.PreloadSize
st.DownloadSpeed = t.DownloadSpeed
st.UploadSpeed = t.UploadSpeed
tst := t.Torrent.Stats()
st.BytesWritten = tst.BytesWritten.Int64()
st.BytesWrittenData = tst.BytesWrittenData.Int64()
st.BytesRead = tst.BytesRead.Int64()
st.BytesReadData = tst.BytesReadData.Int64()
st.BytesReadUsefulData = tst.BytesReadUsefulData.Int64()
st.ChunksWritten = tst.ChunksWritten.Int64()
st.ChunksRead = tst.ChunksRead.Int64()
st.ChunksReadUseful = tst.ChunksReadUseful.Int64()
st.ChunksReadWasted = tst.ChunksReadWasted.Int64()
st.PiecesDirtiedGood = tst.PiecesDirtiedGood.Int64()
st.PiecesDirtiedBad = tst.PiecesDirtiedBad.Int64()
st.TotalPeers = tst.TotalPeers
st.PendingPeers = tst.PendingPeers
st.ActivePeers = tst.ActivePeers
st.ConnectedSeeders = tst.ConnectedSeeders
st.HalfOpenPeers = tst.HalfOpenPeers
files := t.Files()
sort.Slice(files, func(i, j int) bool {
return files[i].Path() < files[j].Path()
})
for i, f := range files {
st.FileStats = append(st.FileStats, TorrentFileStat{
Id: i,
Path: f.Path(),
Length: f.Length(),
})
}
}
return st
}

View File

@@ -1 +0,0 @@
package filecache

View File

@@ -1,69 +0,0 @@
package filecache
import (
"path/filepath"
"sync"
"server/settings"
"server/torr/storage"
"server/torr/storage/state"
"github.com/anacrolix/missinggo/filecache"
"github.com/anacrolix/torrent/metainfo"
storage2 "github.com/anacrolix/torrent/storage"
)
type Storage struct {
storage.Storage
caches map[metainfo.Hash]*filecache.Cache
capacity int64
mu sync.Mutex
}
func NewStorage(capacity int64) storage.Storage {
stor := new(Storage)
stor.capacity = capacity
stor.caches = make(map[metainfo.Hash]*filecache.Cache)
return stor
}
func (s *Storage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (storage2.TorrentImpl, error) {
s.mu.Lock()
defer s.mu.Unlock()
path := filepath.Join(settings.Path, "cache", infoHash.String())
cache, err := filecache.NewCache(path)
if err != nil {
return nil, err
}
cache.SetCapacity(s.capacity)
s.caches[infoHash] = cache
return storage2.NewResourcePieces(cache.AsResourceProvider()).OpenTorrent(info, infoHash)
}
func (s *Storage) GetStats(hash metainfo.Hash) *state.CacheState {
s.mu.Lock()
defer s.mu.Unlock()
return nil
}
func (s *Storage) Clean() {
s.mu.Lock()
defer s.mu.Unlock()
}
func (s *Storage) CloseHash(hash metainfo.Hash) {
if s.caches == nil {
return
}
s.mu.Lock()
defer s.mu.Unlock()
}
func (s *Storage) Close() error {
s.mu.Lock()
defer s.mu.Unlock()
return nil
}

View File

@@ -1,18 +0,0 @@
package state
type CacheState struct {
Hash string
Capacity int64
Filled int64
PiecesLength int64
PiecesCount int
Pieces map[int]ItemState
}
type ItemState struct {
Id int
Accessed int64
BufferSize int64
Completed bool
Hash string
}

View File

@@ -1,8 +1,6 @@
package storage
import (
"server/torr/storage/state"
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/storage"
)
@@ -10,6 +8,5 @@ import (
type Storage interface {
storage.ClientImpl
GetStats(hash metainfo.Hash) *state.CacheState
CloseHash(hash metainfo.Hash)
}

View File

@@ -1,4 +1,4 @@
package memcache
package torrstor
import (
"fmt"
@@ -53,7 +53,6 @@ func (b *BufferPool) GetBuffer(p *Piece) (buff []byte, index int) {
buff = buf.buf
index = id
b.frees--
//fmt.Printf("Get buffer: %v %v %v %p\n", id, p.Id, b.frees, buff)
return
}
}

View File

@@ -1,4 +1,4 @@
package memcache
package torrstor
import (
"log"
@@ -7,8 +7,7 @@ import (
"server/settings"
"server/torr/reader"
"server/torr/storage/state"
"server/utils"
"server/torr/utils"
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/storage"
@@ -101,30 +100,6 @@ func (c *Cache) Close() error {
return nil
}
func (c *Cache) GetState() state.CacheState {
cState := state.CacheState{}
cState.Capacity = c.capacity
cState.PiecesLength = c.pieceLength
cState.PiecesCount = c.pieceCount
cState.Hash = c.hash.HexString()
stats := make(map[int]state.ItemState, 0)
c.muPiece.Lock()
var fill int64 = 0
for _, value := range c.pieces {
stat := value.Stat()
if stat.BufferSize > 0 {
fill += stat.BufferSize
stats[stat.Id] = stat
}
}
c.filled = fill
c.muPiece.Unlock()
cState.Filled = c.filled
cState.Pieces = stats
return cState
}
func (c *Cache) cleanPieces() {
if c.isRemove {
return
@@ -220,7 +195,7 @@ func (c *Cache) ReadersLen() int {
func (c *Cache) AdjustRA(readahead int64) {
c.muReader.Lock()
defer c.muReader.Unlock()
if settings.Get().CacheSize == 0 {
if settings.BTsets.CacheSize == 0 {
c.capacity = readahead * 3
}
for r, _ := range c.readers {

View File

@@ -1,4 +1,4 @@
package memcache
package torrstor
import (
"errors"
@@ -6,8 +6,6 @@ import (
"sync"
"time"
"server/torr/storage/state"
"github.com/anacrolix/torrent/storage"
)
@@ -103,13 +101,10 @@ func (p *Piece) Release() {
p.complete = false
}
func (p *Piece) Stat() state.ItemState {
itm := state.ItemState{
Id: p.Id,
Hash: p.Hash,
Accessed: p.accessed,
Completed: p.complete,
BufferSize: p.Size,
}
return itm
func WriteToDisk(b []byte, off int64) (n int, err error) {
return 0, nil
}
func ReadFromDisk(b []byte, off int64) (n int, err error) {
return 0, nil
}

View File

@@ -1,10 +1,9 @@
package memcache
package torrstor
import (
"sync"
"server/torr/storage"
"server/torr/storage/state"
"github.com/anacrolix/torrent/metainfo"
storage2 "github.com/anacrolix/torrent/storage"
@@ -34,16 +33,6 @@ func (s *Storage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (stor
return ch, nil
}
func (s *Storage) GetStats(hash metainfo.Hash) *state.CacheState {
s.mu.Lock()
defer s.mu.Unlock()
if c, ok := s.caches[hash]; ok {
st := c.GetState()
return &st
}
return nil
}
func (s *Storage) CloseHash(hash metainfo.Hash) {
if s.caches == nil {
return

31
src/server/torr/stream.go Normal file
View File

@@ -0,0 +1,31 @@
package torr
import (
"errors"
"fmt"
"log"
"net/http"
"time"
"github.com/anacrolix/missinggo/httptoo"
)
func (t *Torrent) Stream(fileIndex int, req *http.Request, resp http.ResponseWriter) error {
files := t.Files()
if fileIndex < 0 || fileIndex >= len(files) {
return errors.New("file index out of range")
}
file := files[fileIndex]
reader := t.NewReader(file, 0)
log.Println("Connect client")
resp.Header().Set("Connection", "close")
resp.Header().Set("ETag", httptoo.EncodeQuotedString(fmt.Sprintf("%s/%s", t.Hash().HexString(), file.Path())))
http.ServeContent(resp, req, file.Path(), time.Time{}, reader)
log.Println("Disconnect client")
t.CloseReader(reader)
return nil
}

View File

@@ -3,15 +3,15 @@ package torr
import (
"io"
"log"
"sort"
"sync"
"time"
"server/settings"
"server/utils"
"server/torr/utils"
utils2 "server/utils"
"server/torr/reader"
"server/torr/storage/memcache"
"server/torr/storage/torrstor"
"github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/metainfo"
@@ -51,10 +51,9 @@ type Torrent struct {
status TorrentStatus
muTorrent sync.Mutex
muReader sync.Mutex
bt *BTServer
cache *memcache.Cache
cache *torrstor.Cache
lastTimeSpeed time.Time
DownloadSpeed float64
@@ -74,29 +73,25 @@ type Torrent struct {
progressTicker *time.Ticker
}
func NewTorrent(magnet metainfo.Magnet, infobytes []byte, bt *BTServer) (*Torrent, error) {
switch settings.Get().RetrackersMode {
case 1:
magnet.Trackers = append(magnet.Trackers, utils.GetDefTrackers()...)
case 2:
magnet.Trackers = nil
case 3:
magnet.Trackers = utils.GetDefTrackers()
}
goTorrent, _, err := bt.client.AddTorrentSpec(&torrent.TorrentSpec{
InfoBytes: infobytes,
Trackers: [][]string{magnet.Trackers},
DisplayName: magnet.DisplayName,
InfoHash: magnet.InfoHash,
})
func NewTorrent(spec *torrent.TorrentSpec, bt *BTServer) (*Torrent, error) {
switch settings.BTsets.RetrackersMode {
case 1:
spec.Trackers = append(spec.Trackers, [][]string{utils.GetDefTrackers()}...)
case 2:
spec.Trackers = nil
case 3:
spec.Trackers = [][]string{utils.GetDefTrackers()}
}
goTorrent, _, err := bt.client.AddTorrentSpec(spec)
if err != nil {
return nil, err
}
bt.mu.Lock()
defer bt.mu.Unlock()
if tor, ok := bt.torrents[magnet.InfoHash]; ok {
if tor, ok := bt.torrents[spec.InfoHash]; ok {
return tor, nil
}
@@ -105,12 +100,12 @@ func NewTorrent(magnet metainfo.Magnet, infobytes []byte, bt *BTServer) (*Torren
torr.status = TorrentAdded
torr.lastTimeSpeed = time.Now()
torr.bt = bt
torr.hash = magnet.InfoHash
torr.hash = spec.InfoHash
torr.closed = goTorrent.Closed()
go torr.watch()
bt.torrents[magnet.InfoHash] = torr
bt.torrents[spec.InfoHash] = torr
return torr, nil
}
@@ -119,6 +114,7 @@ func (t *Torrent) WaitInfo() bool {
return false
}
// Close torrent if not info while 10 minutes
tm := time.NewTimer(time.Minute * 10)
select {
@@ -185,17 +181,22 @@ func (t *Torrent) progressEvent() {
t.UploadSpeed = 0
}
t.muTorrent.Unlock()
t.lastTimeSpeed = time.Now()
if t.BytesReadUsefulData > settings.Get().PreloadBufferSize {
adj := int64((int(t.cache.GetState().PiecesLength) * t.Torrent.Stats().ActivePeers) / (1 + t.cache.ReadersLen()))
t.updateRA()
}
func (t *Torrent) updateRA() {
if t.BytesReadUsefulData > settings.BTsets.PreloadBufferSize {
pieceLen := t.Torrent.Info().PieceLength
adj := pieceLen * int64(t.Torrent.Stats().ActivePeers) / int64(1+t.cache.ReadersLen())
switch {
case adj < t.cache.GetState().PiecesLength:
adj = t.cache.GetState().PiecesLength
case adj > t.cache.GetState().PiecesLength*4:
adj = t.cache.GetState().PiecesLength * 4
case adj < pieceLen:
adj = pieceLen
case adj > pieceLen*4:
adj = pieceLen * 4
}
t.cache.AdjustRA(adj)
//log.Println("Status:", t.Name(), "S:", fmt.Sprintf("%8s", utils.Format(t.DownloadSpeed)), "P:", fmt.Sprintf("%2d", t.Torrent.Stats().ActivePeers), "/", fmt.Sprintf("%2d", t.Torrent.Stats().TotalPeers), "R:", t.cache.ReadersLen(), "RA:", utils.Format(float64(adj)))
}
}
@@ -227,31 +228,20 @@ func (t *Torrent) Length() int64 {
}
func (t *Torrent) NewReader(file *torrent.File, readahead int64) *reader.Reader {
t.muReader.Lock()
if t.status == TorrentClosed {
return nil
}
defer t.muReader.Unlock()
reader := reader.NewReader(file)
if readahead <= 0 {
readahead = t.cache.GetState().PiecesLength
}
reader.SetReadahead(readahead)
t.cache.AddReader(reader)
reader := reader.NewReader(t, file, readahead)
return reader
}
func (t *Torrent) CloseReader(reader *reader.Reader) {
t.muReader.Lock()
reader.Close()
t.cache.RemReader(reader)
t.expiredTime = time.Now().Add(time.Second * time.Duration(settings.Get().TorrentDisconnectTimeout))
t.muReader.Unlock()
t.expiredTime = time.Now().Add(time.Second * time.Duration(settings.BTsets.TorrentDisconnectTimeout))
}
func (t *Torrent) GetCache() *memcache.Cache {
func (t *Torrent) GetCache() *torrstor.Cache {
return t.cache
}
@@ -262,6 +252,8 @@ func (t *Torrent) Preload(file *torrent.File, size int64) {
if t.status == TorrentGettingInfo {
t.WaitInfo()
// wait change status
time.Sleep(100 * time.Millisecond)
}
t.muTorrent.Lock()
@@ -271,7 +263,7 @@ func (t *Torrent) Preload(file *torrent.File, size int64) {
}
if size == 0 {
size = settings.Get().PreloadBufferSize
size = settings.BTsets.PreloadBufferSize
}
if size == 0 {
t.muTorrent.Unlock()
@@ -325,7 +317,7 @@ func (t *Torrent) Preload(file *torrent.File, size int64) {
for t.status == TorrentPreload {
t.expiredTime = time.Now().Add(time.Minute * 5)
t.PreloadedBytes = t.Torrent.BytesCompleted()
log.Println("Preload:", file.Torrent().InfoHash().HexString(), bytes.Format(t.PreloadedBytes), "/", bytes.Format(t.PreloadSize), "Speed:", utils.Format(t.DownloadSpeed), "Peers:[", t.Torrent.Stats().ConnectedSeeders, "]", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers)
log.Println("Preload:", file.Torrent().InfoHash().HexString(), bytes.Format(t.PreloadedBytes), "/", bytes.Format(t.PreloadSize), "Speed:", utils2.Format(t.DownloadSpeed), "Peers:[", t.Torrent.Stats().ConnectedSeeders, "]", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers)
if t.PreloadedBytes >= t.PreloadSize {
return
}
@@ -357,66 +349,9 @@ func (t *Torrent) Close() {
t.bt.mu.Lock()
defer t.bt.mu.Unlock()
t.muReader.Lock()
defer t.muReader.Unlock()
if _, ok := t.bt.torrents[t.hash]; ok {
delete(t.bt.torrents, t.hash)
}
t.drop()
}
func (t *Torrent) Stats() TorrentStats {
t.muTorrent.Lock()
defer t.muTorrent.Unlock()
st := TorrentStats{}
st.Name = t.Name()
st.Hash = t.hash.HexString()
st.TorrentStatus = t.status
st.TorrentStatusString = t.status.String()
if t.Torrent != nil {
st.LoadedSize = t.Torrent.BytesCompleted()
st.TorrentSize = t.Length()
st.PreloadedBytes = t.PreloadedBytes
st.PreloadSize = t.PreloadSize
st.DownloadSpeed = t.DownloadSpeed
st.UploadSpeed = t.UploadSpeed
tst := t.Torrent.Stats()
st.BytesWritten = tst.BytesWritten.Int64()
st.BytesWrittenData = tst.BytesWrittenData.Int64()
st.BytesRead = tst.BytesRead.Int64()
st.BytesReadData = tst.BytesReadData.Int64()
st.BytesReadUsefulData = tst.BytesReadUsefulData.Int64()
st.ChunksWritten = tst.ChunksWritten.Int64()
st.ChunksRead = tst.ChunksRead.Int64()
st.ChunksReadUseful = tst.ChunksReadUseful.Int64()
st.ChunksReadWasted = tst.ChunksReadWasted.Int64()
st.PiecesDirtiedGood = tst.PiecesDirtiedGood.Int64()
st.PiecesDirtiedBad = tst.PiecesDirtiedBad.Int64()
st.TotalPeers = tst.TotalPeers
st.PendingPeers = tst.PendingPeers
st.ActivePeers = tst.ActivePeers
st.ConnectedSeeders = tst.ConnectedSeeders
st.HalfOpenPeers = tst.HalfOpenPeers
files := t.Files()
sort.Slice(files, func(i, j int) bool {
return files[i].Path() < files[j].Path()
})
for i, f := range files {
st.FileStats = append(st.FileStats, TorrentFileStat{
Id: i,
Path: f.Path(),
Length: f.Length(),
})
}
}
return st
}

View File

@@ -0,0 +1,35 @@
package utils
import (
"bufio"
"io/ioutil"
"path/filepath"
"strings"
"server/settings"
"github.com/anacrolix/torrent/iplist"
)
func ReadBlockedIP() (ranger iplist.Ranger, err error) {
buf, err := ioutil.ReadFile(filepath.Join(settings.Path, "blocklist"))
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(strings.NewReader(string(buf)))
var ranges []iplist.Range
for scanner.Scan() {
r, ok, err := iplist.ParseBlocklistP2PLine(scanner.Bytes())
if err != nil {
return nil, err
}
if ok {
ranges = append(ranges, r)
}
}
err = scanner.Err()
if len(ranges) > 0 {
ranger = iplist.New(ranges)
}
return
}

View File

@@ -0,0 +1,15 @@
package utils
import (
"runtime"
"runtime/debug"
)
func FreeOSMem() {
debug.FreeOSMemory()
}
func FreeOSMemGC() {
runtime.GC()
debug.FreeOSMemory()
}

View File

@@ -0,0 +1,103 @@
package utils
import (
"encoding/base32"
"io/ioutil"
"math/rand"
"net/http"
"strings"
"golang.org/x/time/rate"
)
var defTrackers = []string{
"http://retracker.local",
"http://bt4.t-ru.org/ann?magnet",
"http://retracker.mgts.by:80/announce",
"http://tracker.city9x.com:2710/announce",
"http://tracker.electro-torrent.pl:80/announce",
"http://tracker.internetwarriors.net:1337/announce",
"http://tracker2.itzmx.com:6961/announce",
"udp4://46.148.18.250:2710",
"udp://opentor.org:2710",
"udp://public.popcorn-tracker.org:6969/announce",
"udp://tracker.opentrackr.org:1337/announce",
"http://bt.svao-ix.ru/announce",
"udp://explodie.org:6969/announce",
//https://github.com/ngosang/trackerslist/blob/master/trackers_best_ip.txt 18.12.2019
"udp4://62.138.0.158:6969/announce",
"udp4://188.241.58.209:6969/announce",
"udp4://93.158.213.92:1337/announce",
"udp4://62.210.97.59:1337/announce",
"udp4://151.80.120.113:2710/announce",
"udp4://151.80.120.115:2710/announce",
"udp4://165.231.0.116:80/announce",
"udp4://208.83.20.20:6969/announce",
"udp4://5.206.54.49:6969/announce",
"udp4://35.156.19.129:6969/announce",
"udp4://37.235.174.46:2710/announce",
"udp4://185.181.60.67:80/announce",
"udp4://54.37.235.149:6969/announce",
"udp4://89.234.156.205:451/announce",
"udp4://159.100.245.181:6969/announce",
"udp4://142.44.243.4:1337/announce",
"udp4://51.15.40.114:80/announce",
"udp4://176.113.71.19:6961/announce",
"udp4://212.47.227.58:6969/announce",
}
var loadedTrackers []string
func GetDefTrackers() []string {
loadNewTracker()
if len(loadedTrackers) == 0 {
return defTrackers
}
return loadedTrackers
}
func loadNewTracker() {
if len(loadedTrackers) > 0 {
return
}
resp, err := http.Get("https://newtrackon.com/api/stable")
if err == nil {
buf, err := ioutil.ReadAll(resp.Body)
if err == nil {
arr := strings.Split(string(buf), "\n")
var ret []string
for _, s := range arr {
s = strings.TrimSpace(s)
if len(s) > 0 {
ret = append(ret, s)
}
}
loadedTrackers = ret
}
}
}
func PeerIDRandom(peer string) string {
randomBytes := make([]byte, 32)
_, err := rand.Read(randomBytes)
if err != nil {
panic(err)
}
return peer + base32.StdEncoding.EncodeToString(randomBytes)[:20-len(peer)]
}
func Limit(i int) *rate.Limiter {
l := rate.NewLimiter(rate.Inf, 0)
if i > 0 {
b := i
if b < 16*1024 {
b = 16 * 1024
}
l = rate.NewLimiter(rate.Limit(i), b)
}
return l
}