parent
afe5f9a232
commit
ed0f8b5c21
63
engine.go
63
engine.go
|
@ -10,12 +10,13 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const boltDbDir = `piece_complete_db`
|
const refreshSec = 3
|
||||||
|
|
||||||
type TorrentStatus struct {
|
type TorrentStatus struct {
|
||||||
DownloadRate int64
|
DownloadRate int64
|
||||||
|
@ -48,6 +49,7 @@ type Engine struct {
|
||||||
upRate int64
|
upRate int64
|
||||||
seeds int64
|
seeds int64
|
||||||
}
|
}
|
||||||
|
fs FileStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Engine) IsAlive() bool {
|
func (o *Engine) IsAlive() bool {
|
||||||
|
@ -60,6 +62,7 @@ func (o *Engine) StartTorrent(idx int64) error {
|
||||||
o.torrCfg.ListenPort = o.settings.ListenPort
|
o.torrCfg.ListenPort = o.settings.ListenPort
|
||||||
o.torrCfg.DataDir = o.settings.DownloadPath
|
o.torrCfg.DataDir = o.settings.DownloadPath
|
||||||
o.torrCfg.DefaultStorage = storage.NewFileWithCompletion(o.settings.DownloadPath, storage.NewMapPieceCompletion())
|
o.torrCfg.DefaultStorage = storage.NewFileWithCompletion(o.settings.DownloadPath, storage.NewMapPieceCompletion())
|
||||||
|
|
||||||
if o.settings.Proxy != "" {
|
if o.settings.Proxy != "" {
|
||||||
if u, err := url.Parse(o.settings.Proxy); err != nil {
|
if u, err := url.Parse(o.settings.Proxy); err != nil {
|
||||||
o.torrCfg.HTTPProxy = func(request *http.Request) (*url.URL, error) { return u, nil }
|
o.torrCfg.HTTPProxy = func(request *http.Request) (*url.URL, error) { return u, nil }
|
||||||
|
@ -82,6 +85,8 @@ func (o *Engine) StartTorrent(idx int64) error {
|
||||||
t := o.torrent
|
t := o.torrent
|
||||||
<-t.GotInfo()
|
<-t.GotInfo()
|
||||||
|
|
||||||
|
o.setStaticFileStatusData(idx)
|
||||||
|
|
||||||
file := o.torrent.Files()[idx]
|
file := o.torrent.Files()[idx]
|
||||||
|
|
||||||
// отключаем загрузку всех файлов
|
// отключаем загрузку всех файлов
|
||||||
|
@ -92,12 +97,8 @@ func (o *Engine) StartTorrent(idx int64) error {
|
||||||
endPieceIndex := (file.Offset() + file.Length()) * int64(t.NumPieces()) / t.Length()
|
endPieceIndex := (file.Offset() + file.Length()) * int64(t.NumPieces()) / t.Length()
|
||||||
o.torrent.DownloadPieces(int(firstPieceIndex), int(endPieceIndex))
|
o.torrent.DownloadPieces(int(firstPieceIndex), int(endPieceIndex))
|
||||||
|
|
||||||
for i := firstPieceIndex; i <= endPieceIndex*5/100; i++ {
|
|
||||||
t.Piece(int(i)).SetPriority(torrent.PiecePriorityNow)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
ticker := time.NewTicker(time.Second)
|
ticker := time.NewTicker(time.Second * refreshSec)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -131,18 +132,34 @@ func (o *Engine) StartTorrent(idx int64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Engine) setStaticFileStatusData(i int64) {
|
||||||
|
o.fs = FileStatus{}
|
||||||
|
file := o.torrent.Files()[i]
|
||||||
|
|
||||||
|
pathParts := strings.Split(file.DisplayPath(), `/`)
|
||||||
|
o.fs.Name = file.DisplayPath()
|
||||||
|
for idx := range pathParts {
|
||||||
|
pathParts[idx] = url.QueryEscape(pathParts[idx])
|
||||||
|
}
|
||||||
|
o.fs.Url = fmt.Sprintf(`http://%s:%d/files/%s`, o.settings.HttpBindHost, o.settings.HttpBindPort, strings.Join(pathParts, `/`))
|
||||||
|
o.fs.Length = file.Length()
|
||||||
|
if o.fs.Length < 0 {
|
||||||
|
o.fs.Length *= -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Engine) updateStats() {
|
func (o *Engine) updateStats() {
|
||||||
stats := o.torrent.Stats()
|
stats := o.torrent.Stats()
|
||||||
if o.status.lastBytesReadData == 0 {
|
if o.status.lastBytesReadData == 0 {
|
||||||
o.status.downRate = 0
|
o.status.downRate = 0
|
||||||
} else {
|
} else {
|
||||||
o.status.downRate = (stats.BytesReadData.Int64() - o.status.lastBytesReadData) / 1024
|
o.status.downRate = (stats.BytesReadData.Int64() - o.status.lastBytesReadData) / 1024 / refreshSec
|
||||||
}
|
}
|
||||||
o.status.lastBytesReadData = stats.BytesReadData.Int64()
|
o.status.lastBytesReadData = stats.BytesReadData.Int64()
|
||||||
if o.status.lastBytesWrittenData == 0 {
|
if o.status.lastBytesWrittenData == 0 {
|
||||||
o.status.upRate = 0
|
o.status.upRate = 0
|
||||||
} else {
|
} else {
|
||||||
o.status.upRate = (stats.BytesWrittenData.Int64() - o.status.lastBytesWrittenData) / 1024
|
o.status.upRate = (stats.BytesWrittenData.Int64() - o.status.lastBytesWrittenData) / 1024 / refreshSec
|
||||||
}
|
}
|
||||||
o.status.lastBytesWrittenData = stats.BytesWrittenData.Int64()
|
o.status.lastBytesWrittenData = stats.BytesWrittenData.Int64()
|
||||||
o.status.seeds = int64(stats.ConnectedSeeders)
|
o.status.seeds = int64(stats.ConnectedSeeders)
|
||||||
|
@ -156,28 +173,15 @@ func (o *Engine) Status() TorrentStatus {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
func (o *Engine) FileStatus(i int) (FileStatus, error) {
|
func (o *Engine) FileStatus(i int) (FileStatus, error) {
|
||||||
fs := FileStatus{}
|
|
||||||
if i < 0 || i > len(o.torrent.Files())-1 {
|
if i < 0 || i > len(o.torrent.Files())-1 {
|
||||||
return fs, fmt.Errorf(`file index out of range: %d`, i)
|
return o.fs, fmt.Errorf(`file index out of range: %d`, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := o.torrent.Files()[i]
|
file := o.torrent.Files()[i]
|
||||||
|
o.fs.Progress = int64(float64(file.BytesCompleted()) / float64(file.Length()) * 100.0)
|
||||||
pathParts := strings.Split(file.DisplayPath(), `/`)
|
if o.fs.Progress < 0 {
|
||||||
fs.Name = file.DisplayPath()
|
o.fs.Progress *= -1
|
||||||
for idx := range pathParts {
|
|
||||||
pathParts[idx] = url.QueryEscape(pathParts[idx])
|
|
||||||
}
|
}
|
||||||
fs.Url = fmt.Sprintf(`http://%s:%d/files/%s`, o.settings.HttpBindHost, o.settings.HttpBindPort, strings.Join(pathParts, `/`))
|
return o.fs, nil
|
||||||
fs.Progress = int64(float64(file.BytesCompleted()) / float64(file.Length()) * 100.0)
|
|
||||||
if fs.Progress < 0 {
|
|
||||||
fs.Progress *= -1
|
|
||||||
}
|
|
||||||
fs.Length = file.Length()
|
|
||||||
if fs.Length < 0 {
|
|
||||||
fs.Length *= -1
|
|
||||||
}
|
|
||||||
return fs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Engine) Stop() {
|
func (o *Engine) Stop() {
|
||||||
|
@ -201,6 +205,7 @@ func (o *Engine) Stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
o.syncDebug(`torrent engine stopped`)
|
o.syncDebug(`torrent engine stopped`)
|
||||||
|
o.shutdown()
|
||||||
close(o.msgs)
|
close(o.msgs)
|
||||||
o.alive = false
|
o.alive = false
|
||||||
}()
|
}()
|
||||||
|
@ -276,8 +281,6 @@ func (o *Engine) syncInfo(t string, a ...interface{}) {
|
||||||
func (o *Engine) GetFileHandler(target *torrent.File) func(http.ResponseWriter, *http.Request) {
|
func (o *Engine) GetFileHandler(target *torrent.File) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
entry := target.NewReader()
|
entry := target.NewReader()
|
||||||
entry.SetReadahead(target.Length() / 100)
|
|
||||||
entry.SetResponsive()
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := entry.Close(); err != nil {
|
if err := entry.Close(); err != nil {
|
||||||
|
@ -285,9 +288,7 @@ func (o *Engine) GetFileHandler(target *torrent.File) func(http.ResponseWriter,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pathParts := strings.Split(target.DisplayPath(), `/`)
|
w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(target.DisplayPath()))
|
||||||
|
|
||||||
w.Header().Set("Content-Disposition", "attachment; filename=\""+pathParts[len(pathParts)-1]+"\"")
|
|
||||||
http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
|
http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module gorrent
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/anacrolix/missinggo/v2 v2.5.2
|
||||||
github.com/anacrolix/torrent v1.41.0
|
github.com/anacrolix/torrent v1.41.0
|
||||||
github.com/go-python/gopy v0.4.0
|
github.com/go-python/gopy v0.4.0
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||||
|
@ -18,7 +19,6 @@ require (
|
||||||
github.com/anacrolix/log v0.10.1-0.20220123034749-3920702c17f8 // indirect
|
github.com/anacrolix/log v0.10.1-0.20220123034749-3920702c17f8 // indirect
|
||||||
github.com/anacrolix/missinggo v1.3.0 // indirect
|
github.com/anacrolix/missinggo v1.3.0 // indirect
|
||||||
github.com/anacrolix/missinggo/perf v1.0.0 // indirect
|
github.com/anacrolix/missinggo/perf v1.0.0 // indirect
|
||||||
github.com/anacrolix/missinggo/v2 v2.5.2 // indirect
|
|
||||||
github.com/anacrolix/mmsg v1.0.0 // indirect
|
github.com/anacrolix/mmsg v1.0.0 // indirect
|
||||||
github.com/anacrolix/multiless v0.2.0 // indirect
|
github.com/anacrolix/multiless v0.2.0 // indirect
|
||||||
github.com/anacrolix/stm v0.3.0 // indirect
|
github.com/anacrolix/stm v0.3.0 // indirect
|
||||||
|
@ -57,6 +57,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||||
github.com/rs/dnscache v0.0.0-20210201191234-295bba877686 // indirect
|
github.com/rs/dnscache v0.0.0-20210201191234-295bba877686 // indirect
|
||||||
|
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 // indirect
|
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
|
|
|
@ -4,6 +4,8 @@ import "context"
|
||||||
|
|
||||||
var version = `1.0.0`
|
var version = `1.0.0`
|
||||||
|
|
||||||
|
const defaultMaxReadaheadBytes = 20 * 1024 * 1024
|
||||||
|
|
||||||
func GetMetaFromFile(path string) (*Info, error) {
|
func GetMetaFromFile(path string) (*Info, error) {
|
||||||
info := &Info{}
|
info := &Info{}
|
||||||
if err := info.LoadFile(path); err != nil {
|
if err := info.LoadFile(path); err != nil {
|
||||||
|
|
Loading…
Reference in New Issue