diff --git a/.gitignore b/.gitignore
index 01e8676..81458b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,5 @@ pkg/
bin/
dist/
toolchains/
+/src/crawshaw.io/
+/src/go.etcd.io/
diff --git a/build-all.sh b/build-all.sh
index 1557437..585af0c 100755
--- a/build-all.sh
+++ b/build-all.sh
@@ -23,7 +23,22 @@ PLATFORMS_ARM="linux"
type setopt >/dev/null 2>&1
export GOPATH="${PWD}"
-GOBIN="/usr/local/go_111/bin/go"
+GOBIN="/usr/local/go/bin/go"
+
+[ -d src/github.com/alexflint/go-arg ] && go get -v github.com/alexflint/go-arg
+[ -d src/github.com/anacrolix/dht ] && go get -v github.com/anacrolix/dht
+[ -d src/github.com/anacrolix/missinggo/httptoo ] && go get -v github.com/anacrolix/missinggo/httptoo
+[ -d src/github.com/anacrolix/torrent ] && go get -v github.com/anacrolix/torrent
+[ -d src/github.com/anacrolix/torrent/iplist ] && go get -v github.com/anacrolix/torrent/iplist
+[ -d src/github.com/anacrolix/torrent/metainfo ] && go get -v github.com/anacrolix/torrent/metainfo
+[ -d src/github.com/anacrolix/utp ] && go get -v github.com/anacrolix/utp
+[ -d src/github.com/labstack/echo ] && go get -v github.com/labstack/echo
+[ -d src/github.com/labstack/echo/middleware ] && go get -v github.com/labstack/echo/middleware
+[ -d src/github.com/labstack/gommon/bytes ] && go get -v github.com/labstack/gommon/bytes
+[ -d src/github.com/pion/webrtc/v2 ] && go get -v github.com/pion/webrtc/v2
+[ -d src/go.etcd.io/bbolt ] && go get -v go.etcd.io/bbolt
+
+#ln -s . src/github.com/pion/webrtc/v2
$GOBIN version
diff --git a/src/main/test.go b/src/main/test.go
deleted file mode 100644
index ba18244..0000000
--- a/src/main/test.go
+++ /dev/null
@@ -1,143 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "sync"
- "time"
-
- "server/utils"
- "server/version"
-
- "github.com/anacrolix/torrent"
-)
-
-/*
-{
- "Name": "TorrServer",
- "Version": "1.1.71",
- "BuildDate": "17.05.2019",
- "Links": {
- "android-386": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-android-386",
- "android-amd64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-android-amd64",
- "android-arm64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-android-arm64",
- "android-arm7": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-android-arm7",
- "darwin-amd64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-darwin-amd64",
- "linux-386": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-386",
- "linux-amd64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-amd64",
- "linux-arm5": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-arm5",
- "linux-arm6": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-arm6",
- "linux-arm64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-arm64",
- "linux-arm7": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-arm7",
- "linux-mips": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-mips",
- "linux-mips64": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-mips64",
- "linux-mips64le": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-mips64le",
- "linux-mipsle": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-linux-mipsle",
- "windows-386.exe": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-windows-386.exe",
- "windows-amd64.exe": "https://github.com/YouROK/TorrServer/releases/download/1.1.71/TorrServer-windows-amd64.exe"
- }
-}
-*/
-
-type release struct {
- Version string
- Links map[string]string
-}
-
-func mkReleasesJS() {
- var releases []release
- for i := 65; i <= version.VerInt; i++ {
- links := map[string]string{
- "android-386": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-android-386", i),
- "android-amd64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-android-amd64", i),
- "android-arm64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-android-arm64", i),
- "android-arm7": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-android-arm7", i),
- "darwin-amd64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-darwin-amd64", i),
- "linux-386": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-386", i),
- "linux-amd64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-amd64", i),
- "linux-arm5": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-arm5", i),
- "linux-arm6": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-arm6", i),
- "linux-arm64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-arm64", i),
- "linux-arm7": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-arm7", i),
- "linux-mips": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-mips", i),
- "linux-mips64": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-mips64", i),
- "linux-mips64le": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-mips64le", i),
- "linux-mipsle": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-linux-mipsle", i),
- "windows-386.exe": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-windows-386.exe", i),
- "windows-amd64.exe": fmt.Sprintf("https://github.com/YouROK/TorrServer/releases/download/1.1.%d/TorrServer-windows-amd64.exe", i),
- }
- rel := release{
- Version: fmt.Sprintf("1.1.%d", i),
- Links: links,
- }
- releases = append(releases, rel)
- }
- buf, _ := json.MarshalIndent(releases, "", " ")
- if len(buf) > 0 {
- ioutil.WriteFile("/home/yourok/surge/torrserve/releases.json", buf, 0666)
- }
-}
-
-func test() {
- config := torrent.NewDefaultClientConfig()
-
- config.EstablishedConnsPerTorrent = 20
- config.HalfOpenConnsPerTorrent = 65
- config.DisableIPv6 = true
- config.NoDHT = true
-
- client, err := torrent.NewClient(config)
- if err != nil {
- log.Fatal(err)
- }
-
- //Ubuntu
- t, err := client.AddMagnet("magnet:?xt=urn:btih:e4be9e4db876e3e3179778b03e906297be5c8dbe&dn=ubuntu-18.04-desktop-amd64.iso&tr=http%3a%2f%2ftorrent.ubuntu.com%3a6969%2fannounce&tr=http%3a%2f%2fipv6.torrent.ubuntu.com%3a6969%2fannounce")
- if err != nil {
- log.Fatal(err)
- }
- <-t.GotInfo()
- file := t.Files()[0]
-
- reader := file.NewReader()
- var wa sync.WaitGroup
- wa.Add(1)
-
- go func() {
- buf := make([]byte, t.Info().PieceLength)
- for {
- _, err := reader.Read(buf)
- if err != nil {
- break
- }
- }
- wa.Done()
- }()
-
- go func() {
- cl := t.Closed()
- lastTimeSpeed := time.Now()
- DownloadSpeed := 0.0
- BytesReadUsefulData := int64(0)
- for {
- select {
- case <-cl:
- return
- default:
- client.WriteStatus(os.Stdout)
- st := t.Stats()
- deltaDlBytes := st.BytesReadUsefulData.Int64() - BytesReadUsefulData
- deltaTime := time.Since(lastTimeSpeed).Seconds()
- DownloadSpeed = float64(deltaDlBytes) / deltaTime
- BytesReadUsefulData = st.BytesReadUsefulData.Int64()
- lastTimeSpeed = time.Now()
- fmt.Println("DL speed:", utils.Format(DownloadSpeed))
- }
- time.Sleep(time.Second)
- }
- }()
- wa.Wait()
-}
diff --git a/src/server/Server.go b/src/server/Server.go
deleted file mode 100644
index bad60a0..0000000
--- a/src/server/Server.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package server
-
-import (
- "fmt"
-
- "server/settings"
- "server/web"
-)
-
-func Start(settingsPath, port string) {
- settings.Path = settingsPath
- err := settings.ReadSettings()
- if err != nil {
- fmt.Println("Error read settings:", err)
- }
- if port == "" {
- port = "8090"
- }
- server.Start(port)
-}
-
-func WaitServer() string {
- err := server.Wait()
- if err != nil {
- return err.Error()
- }
- return ""
-}
-
-func Stop() {
- go server.Stop()
- settings.CloseDB()
-}
diff --git a/src/server/log/log.go b/src/server/log/log.go
new file mode 100644
index 0000000..348bda1
--- /dev/null
+++ b/src/server/log/log.go
@@ -0,0 +1,9 @@
+package log
+
+import (
+ "log"
+)
+
+func TLogln(v ...interface{}) {
+ log.Println(v...)
+}
diff --git a/src/server/server.go b/src/server/server.go
new file mode 100644
index 0000000..8573c44
--- /dev/null
+++ b/src/server/server.go
@@ -0,0 +1,26 @@
+package server
+
+import (
+ "server/settings"
+)
+
+func Start(settingsPath, port string, roSets bool) {
+ settings.InitSets(settingsPath, roSets)
+ if port == "" {
+ port = "8090"
+ }
+ //server.Start(port)
+}
+
+func WaitServer() string {
+ //err := server.Wait()
+ // if err != nil {
+ // return err.Error()
+ // }
+ return ""
+}
+
+func Stop() {
+ // go server.Stop()
+ settings.CloseDB()
+}
diff --git a/src/server/settings/DB.go b/src/server/settings/DB.go
deleted file mode 100644
index 329aff5..0000000
--- a/src/server/settings/DB.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package settings
-
-import (
- "fmt"
- "path/filepath"
-
- bolt "go.etcd.io/bbolt"
-)
-
-var (
- db *bolt.DB
- dbViewedName = []byte("Viewed")
- dbInfosName = []byte("Infos")
- dbTorrentsName = []byte("Torrents")
- dbSettingsName = []byte("Settings")
- Path string
-)
-
-func openDB() error {
- if db != nil {
- return nil
- }
-
- var err error
- var ro = Get().ReadOnlyMode
- db, err = bolt.Open(filepath.Join(Path, "torrserver.db"), 0666, &bolt.Options{ReadOnly: ro})
- if err != nil {
- fmt.Println(err)
- return err
- }
-
- err = db.Update(func(tx *bolt.Tx) error {
- _, err = tx.CreateBucketIfNotExists(dbSettingsName)
- if err != nil {
- return fmt.Errorf("could not create Settings bucket: %v", err)
- }
- _, err = tx.CreateBucketIfNotExists(dbTorrentsName)
- if err != nil {
- return fmt.Errorf("could not create Torrents bucket: %v", err)
- }
- return nil
- })
- if err != nil {
- CloseDB()
- }
- return err
-}
-
-func CloseDB() {
- if db != nil {
- db.Close()
- db = nil
- }
-}
diff --git a/src/server/settings/Info.go b/src/server/settings/Info.go
deleted file mode 100644
index afd9280..0000000
--- a/src/server/settings/Info.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package settings
-
-import (
- "fmt"
- "strings"
-
- bolt "go.etcd.io/bbolt"
-)
-
-func AddInfo(hash, info string) error {
- err := openDB()
- if err != nil {
- return err
- }
-
- infoe := GetInfo(hash)
- if infoe != "{}" {
- return nil // already filled
- }
-
- hash = strings.ToUpper(hash)
- return db.Update(func(tx *bolt.Tx) error {
- dbt, err := tx.CreateBucketIfNotExists([]byte(dbInfosName))
- if err != nil {
- return err
- }
-
- dbi, err := dbt.CreateBucketIfNotExists([]byte(hash))
- if err != nil {
- return err
- }
-
- err = dbi.Put([]byte("Info"), []byte(info))
- if err != nil {
- return fmt.Errorf("error save torrent info %v", err)
- }
- return nil
- })
-}
-
-func GetInfo(hash string) string {
- err := openDB()
- if err != nil {
- return "{}"
- }
-
- hash = strings.ToUpper(hash)
- ret := "{}"
- err = db.View(func(tx *bolt.Tx) error {
- hdb := tx.Bucket(dbInfosName)
- if hdb == nil {
- return fmt.Errorf("could not find torrent info")
- }
- hdb = hdb.Bucket([]byte(hash))
- if hdb != nil {
- info := hdb.Get([]byte("Info"))
- if info == nil {
- return fmt.Errorf("error get torrent info")
- }
- ret = string(info)
- return nil
- }
- return nil
- })
- return ret
-}
diff --git a/src/server/settings/Settings.go b/src/server/settings/Settings.go
deleted file mode 100644
index be52e33..0000000
--- a/src/server/settings/Settings.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package settings
-
-import (
- "encoding/json"
- "fmt"
- "time"
-
- bolt "go.etcd.io/bbolt"
-)
-
-var (
- sets *Settings
- StartTime time.Time
-)
-
-func init() {
- sets = new(Settings)
- sets.CacheSize = 200 * 1024 * 1024
- sets.EnableDebug = false
- sets.PreloadBufferSize = 20 * 1024 * 1024
- sets.ConnectionsLimit = 20
- sets.DhtConnectionLimit = 500
- sets.RetrackersMode = 1
- sets.TorrentDisconnectTimeout = 30
- StartTime = time.Now()
-}
-
-type Settings struct {
- CacheSize int64 // in byte, def 200 mb
- PreloadBufferSize int64 // in byte, buffer for preload
-
- RetrackersMode int //0 - don`t add, 1 - add retrackers, 2 - remove retrackers
-
- //BT Config
- EnableIPv6 bool
- EnableDebug bool
- DisableTCP bool
- DisableUTP bool
- DisableUPNP bool
- DisableDHT bool
- DisableUpload bool
- ReadOnlyMode bool
- Encryption int // 0 - Enable, 1 - disable, 2 - force
- DownloadRateLimit int // in kb, 0 - inf
- UploadRateLimit int // in kb, 0 - inf
- ConnectionsLimit int
- DhtConnectionLimit int // 0 - inf
- PeersListenPort int
-
- TorrentDisconnectTimeout int // in seconds
-}
-
-func Get() *Settings {
- return sets
-}
-
-func (s *Settings) String() string {
- buf, _ := json.MarshalIndent(sets, "", " ")
- return string(buf)
-}
-
-func ReadSettings() error {
- err := openDB()
- if err != nil {
- return err
- }
- buf := make([]byte, 0)
- err = db.View(func(tx *bolt.Tx) error {
- sdb := tx.Bucket(dbSettingsName)
- if sdb == nil {
- return fmt.Errorf("error load settings")
- }
-
- buf = sdb.Get([]byte("json"))
- if buf == nil {
- return fmt.Errorf("error load settings")
- }
- return nil
- })
- err = json.Unmarshal(buf, sets)
- if err != nil {
- return err
- }
- if sets.ConnectionsLimit <= 0 {
- sets.ConnectionsLimit = 20
- }
- if sets.DhtConnectionLimit < 0 {
- sets.DhtConnectionLimit = 1000
- }
- if sets.CacheSize < 0 {
- sets.CacheSize = 200 * 1024 * 1024
- }
-
- if sets.TorrentDisconnectTimeout < 1 {
- sets.TorrentDisconnectTimeout = 1
- }
- return nil
-}
-
-func SaveSettings() error {
- err := openDB()
- if err != nil {
- return err
- }
-
- buf, err := json.Marshal(sets)
- if err != nil {
- return err
- }
-
- return db.Update(func(tx *bolt.Tx) error {
- setsDB, err := tx.CreateBucketIfNotExists(dbSettingsName)
- if err != nil {
- return err
- }
- return setsDB.Put([]byte("json"), []byte(buf))
- })
-}
-
-func SetRDB() {
- SaveSettings()
- fmt.Println("Enable Read-only DB mode")
- CloseDB()
- sets.ReadOnlyMode = true
-}
diff --git a/src/server/settings/Torrent.go b/src/server/settings/Torrent.go
deleted file mode 100644
index 99ff154..0000000
--- a/src/server/settings/Torrent.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package settings
-
-import (
- "encoding/binary"
- "fmt"
-
- bolt "go.etcd.io/bbolt"
-)
-
-type Torrent struct {
- Name string
- Magnet string
- InfoBytes []byte
- Hash string
- Size int64
- Timestamp int64
-
- Files []File
-}
-
-type File struct {
- Name string
- Id int
- Size int64
-}
-
-func SaveTorrentDB(torrent *Torrent) error {
- err := openDB()
- if err != nil {
- return err
- }
-
- return db.Update(func(tx *bolt.Tx) error {
- dbt, err := tx.CreateBucketIfNotExists(dbTorrentsName)
- if err != nil {
- return fmt.Errorf("could not create Torrents bucket: %v", err)
- }
- fmt.Println("Save torrent:", torrent.Name)
- hdb, err := dbt.CreateBucketIfNotExists([]byte(torrent.Hash))
- if err != nil {
- return fmt.Errorf("could not create Torrent bucket: %v", err)
- }
-
- err = hdb.Put([]byte("Name"), []byte(torrent.Name))
- if err != nil {
- return fmt.Errorf("error save torrent: %v", err)
- }
- err = hdb.Put([]byte("Link"), []byte(torrent.Magnet))
- if err != nil {
- return fmt.Errorf("error save torrent: %v", err)
- }
- err = hdb.Put([]byte("InfoBytes"), torrent.InfoBytes)
- if err != nil {
- return fmt.Errorf("error save torrent: %v", err)
- }
- err = hdb.Put([]byte("Size"), i2b(torrent.Size))
- if err != nil {
- return fmt.Errorf("error save torrent: %v", err)
- }
- err = hdb.Put([]byte("Timestamp"), i2b(torrent.Timestamp))
- if err != nil {
- return fmt.Errorf("error save torrent: %v", err)
- }
-
- fdb, err := hdb.CreateBucketIfNotExists([]byte("Files"))
- if err != nil {
- return fmt.Errorf("error save torrent files: %v", err)
- }
-
- for _, f := range torrent.Files {
- ffdb, err := fdb.CreateBucketIfNotExists([]byte(f.Name))
- if err != nil {
- return fmt.Errorf("error save torrent files: %v", err)
- }
-
- err = ffdb.Put([]byte("Id"), i2b(int64(f.Id)))
- if err != nil {
- return fmt.Errorf("error save torrent files: %v", err)
- }
-
- err = ffdb.Put([]byte("Size"), i2b(f.Size))
- if err != nil {
- return fmt.Errorf("error save torrent files: %v", err)
- }
- }
-
- return nil
- })
-}
-
-func RemoveTorrentDB(hash string) error {
- err := openDB()
- if err != nil {
- return err
- }
-
- return db.Update(func(tx *bolt.Tx) error {
- dbt := tx.Bucket(dbTorrentsName)
- if dbt == nil {
- return fmt.Errorf("could not find torrent")
- }
-
- return dbt.DeleteBucket([]byte(hash))
- })
-}
-
-func LoadTorrentDB(hash string) (*Torrent, error) {
- err := openDB()
- if err != nil {
- return nil, err
- }
-
- var torr *Torrent
- err = db.View(func(tx *bolt.Tx) error {
- hdb := tx.Bucket(dbTorrentsName)
- if hdb == nil {
- return fmt.Errorf("could not find torrent")
- }
- hdb = hdb.Bucket([]byte(hash))
- if hdb != nil {
- torr = new(Torrent)
- torr.Hash = string(hash)
- tmp := hdb.Get([]byte("Name"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Name = string(tmp)
-
- tmp = hdb.Get([]byte("Link"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Magnet = string(tmp)
-
- tmp = hdb.Get([]byte("InfoBytes"))
- if len(tmp) > 0 {
- torr.InfoBytes = tmp
- } else {
- torr.InfoBytes = nil
- }
-
- tmp = hdb.Get([]byte("Size"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Size = b2i(tmp)
-
- tmp = hdb.Get([]byte("Timestamp"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Timestamp = b2i(tmp)
-
- fdb := hdb.Bucket([]byte("Files"))
- if fdb == nil {
- return fmt.Errorf("error load torrent files")
- }
- cf := fdb.Cursor()
- for fn, _ := cf.First(); fn != nil; fn, _ = cf.Next() {
- file := File{Name: string(fn)}
- ffdb := fdb.Bucket(fn)
- if ffdb == nil {
- return fmt.Errorf("error load torrent files")
- }
-
- tmp := ffdb.Get([]byte("Id"))
- if tmp == nil {
- return fmt.Errorf("error load torrent file")
- }
- file.Id = int(b2i(tmp))
-
- tmp = ffdb.Get([]byte("Size"))
- if tmp == nil {
- return fmt.Errorf("error load torrent file")
- }
- file.Size = b2i(tmp)
-
- torr.Files = append(torr.Files, file)
- }
- SortFiles(torr.Files)
- }
- return nil
- })
- return torr, err
-}
-
-func LoadTorrentsDB() ([]*Torrent, error) {
- err := openDB()
- if err != nil {
- return nil, err
- }
-
- torrs := make([]*Torrent, 0)
- err = db.View(func(tx *bolt.Tx) error {
- tdb := tx.Bucket(dbTorrentsName)
- c := tdb.Cursor()
- for h, _ := c.First(); h != nil; h, _ = c.Next() {
- hdb := tdb.Bucket(h)
- if hdb != nil {
- torr := new(Torrent)
- torr.Hash = string(h)
- tmp := hdb.Get([]byte("Name"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Name = string(tmp)
-
- tmp = hdb.Get([]byte("Link"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Magnet = string(tmp)
-
- tmp = hdb.Get([]byte("Size"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Size = b2i(tmp)
-
- tmp = hdb.Get([]byte("Timestamp"))
- if tmp == nil {
- return fmt.Errorf("error load torrent")
- }
- torr.Timestamp = b2i(tmp)
-
- fdb := hdb.Bucket([]byte("Files"))
- if fdb == nil {
- return fmt.Errorf("error load torrent files")
- }
- cf := fdb.Cursor()
- for fn, _ := cf.First(); fn != nil; fn, _ = cf.Next() {
- file := File{Name: string(fn)}
- ffdb := fdb.Bucket(fn)
- if ffdb == nil {
- return fmt.Errorf("error load torrent files")
- }
-
- tmp := ffdb.Get([]byte("Id"))
- if tmp == nil {
- return fmt.Errorf("error load torrent file")
- }
- file.Id = int(b2i(tmp))
-
- tmp = ffdb.Get([]byte("Size"))
- if tmp == nil {
- return fmt.Errorf("error load torrent file")
- }
- file.Size = b2i(tmp)
-
- torr.Files = append(torr.Files, file)
- }
- SortFiles(torr.Files)
- torrs = append(torrs, torr)
- }
- }
- return nil
- })
- return torrs, err
-}
-
-func i2b(v int64) []byte {
- b := make([]byte, 8)
- binary.BigEndian.PutUint64(b, uint64(v))
- return b
-}
-
-func b2i(v []byte) int64 {
- return int64(binary.BigEndian.Uint64(v))
-}
diff --git a/src/server/settings/UsableFiles.go b/src/server/settings/UsableFiles.go
deleted file mode 100644
index 42a1c45..0000000
--- a/src/server/settings/UsableFiles.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package settings
-
-import (
- "path/filepath"
- "sort"
- "strings"
-)
-
-var (
- uFiles = map[string]interface{}{
- ".3g2": nil,
- ".3gp": nil,
- ".aaf": nil,
- ".asf": nil,
- ".avchd": nil,
- ".avi": nil,
- ".drc": nil,
- ".flv": nil,
- ".m2v": nil,
- ".m4p": nil,
- ".m4v": nil,
- ".mkv": nil,
- ".mng": nil,
- ".mov": nil,
- ".mp2": nil,
- ".mp4": nil,
- ".mpe": nil,
- ".mpeg": nil,
- ".mpg": nil,
- ".mpv": nil,
- ".mxf": nil,
- ".nsv": nil,
- ".ogg": nil,
- ".ogv": nil,
- ".ts": nil,
- ".m2ts": nil,
- ".mts": nil,
- ".qt": nil,
- ".rm": nil,
- ".rmvb": nil,
- ".roq": nil,
- ".svi": nil,
- ".vob": nil,
- ".webm": nil,
- ".wmv": nil,
- ".yuv": nil,
-
- ".aac": nil,
- ".aiff": nil,
- ".ape": nil,
- ".au": nil,
- ".flac": nil,
- ".gsm": nil,
- ".it": nil,
- ".m3u": nil,
- ".m4a": nil,
- ".mid": nil,
- ".mod": nil,
- ".mp3": nil,
- ".mpa": nil,
- ".pls": nil,
- ".ra": nil,
- ".s3m": nil,
- ".sid": nil,
- ".wav": nil,
- ".wma": nil,
- ".xm": nil,
- }
-)
-
-func SortFiles(files []File) {
- sort.Slice(files, func(i, j int) bool {
- if haveUsable(files[i].Name) && !haveUsable(files[j].Name) {
- return true
- }
- if !haveUsable(files[i].Name) && haveUsable(files[j].Name) {
- return false
- }
-
- return files[i].Name < files[j].Name
- })
-}
-
-func haveUsable(name string) bool {
- ext := strings.ToLower(filepath.Ext(name))
- _, ok := uFiles[ext]
- return ok
-}
diff --git a/src/server/settings/Viewed.go b/src/server/settings/Viewed.go
deleted file mode 100644
index d18f305..0000000
--- a/src/server/settings/Viewed.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package settings
-
-import (
- "fmt"
-
- bolt "go.etcd.io/bbolt"
-)
-
-func SetViewed(hash, filename string) error {
- err := openDB()
- if err != nil {
- return err
- }
-
- return db.Update(func(tx *bolt.Tx) error {
- dbt, err := tx.CreateBucketIfNotExists(dbViewedName)
- if err != nil {
- return fmt.Errorf("error save viewed %v", err)
- }
- hdb, err := dbt.CreateBucketIfNotExists([]byte(hash))
- if err != nil {
- return fmt.Errorf("error save viewed %v", err)
- }
-
- err = hdb.Put([]byte(filename), []byte{1})
- if err != nil {
- return fmt.Errorf("error save viewed %v", err)
- }
- return nil
- })
-}
-
-func RemTorrentViewed(hash string) error {
- err := openDB()
- if err != nil {
- return err
- }
-
- return db.Update(func(tx *bolt.Tx) error {
- dbt := tx.Bucket(dbViewedName)
- if dbt == nil {
- return nil
- }
- err = dbt.DeleteBucket([]byte(hash))
- if err == nil || err == bolt.ErrBucketNotFound {
- return nil
- }
-
- return err
- })
-}
-
-func GetViewed(hash, filename string) bool {
- err := openDB()
- if err != nil {
- return false
- }
- viewed := false
- err = db.View(func(tx *bolt.Tx) error {
- hdb := tx.Bucket(dbViewedName)
- if hdb == nil {
- return fmt.Errorf("error get viewed")
- }
- hdb = hdb.Bucket([]byte(hash))
- if hdb != nil {
- vw := hdb.Get([]byte(filename))
- viewed = vw != nil && vw[0] == 1
- }
- return nil
- })
- return viewed
-}
-
-func GetViewedList() map[string][]string {
- err := openDB()
- if err != nil {
- return nil
- }
-
- var list = make(map[string][]string)
-
- err = db.View(func(tx *bolt.Tx) error {
- rdb := tx.Bucket(dbViewedName)
- if rdb == nil {
- return fmt.Errorf("could not find torrent")
- }
-
- rdb.ForEach(func(hash, _ []byte) error {
- hdb := rdb.Bucket(hash)
- fdb := hdb.Bucket([]byte("Files"))
- fdb.ForEach(func(fileName, _ []byte) error {
- vw := fdb.Get(fileName)
- if vw != nil && vw[0] == 1 {
- list[string(hash)] = append(list[string(hash)], string(fileName))
- }
- return nil
- })
- return nil
- })
- return nil
- })
- return list
-}
diff --git a/src/server/settings/db.go b/src/server/settings/db.go
new file mode 100644
index 0000000..0159905
--- /dev/null
+++ b/src/server/settings/db.go
@@ -0,0 +1,179 @@
+package settings
+
+import (
+ "path/filepath"
+ "strings"
+
+ bolt "go.etcd.io/bbolt"
+ "server/log"
+)
+
+type TDB struct {
+ Path string
+ ReadOnly bool
+ db *bolt.DB
+}
+
+func NewTDB(path string, readOnly bool) *TDB {
+ db, err := bolt.Open(filepath.Join(path, "config.db"), 0666, nil)
+ if err != nil {
+ log.TLogln(err)
+ return nil
+ }
+
+ tdb := new(TDB)
+ tdb.db = db
+ tdb.Path = path
+ tdb.ReadOnly = readOnly
+ return tdb
+}
+
+func (v *TDB) CloseDB() {
+ if v.db != nil {
+ v.db.Close()
+ v.db = nil
+ }
+}
+
+func (v *TDB) Get(xpath, name string) []byte {
+ spath := strings.Split(xpath, "/")
+ if len(spath) == 0 {
+ return nil
+ }
+ var ret []byte
+ err := v.db.View(func(tx *bolt.Tx) error {
+ buckt := tx.Bucket([]byte(spath[0]))
+ if buckt == nil {
+ return nil
+ }
+
+ for i, p := range spath {
+ if i == 0 {
+ continue
+ }
+ buckt = buckt.Bucket([]byte(p))
+ if buckt == nil {
+ return nil
+ }
+ }
+
+ ret = buckt.Get([]byte(name))
+ return nil
+ })
+
+ if err != nil {
+ log.TLogln("Error get sets", xpath+"/"+name, ", error:", err)
+ }
+
+ return ret
+}
+
+func (v *TDB) Set(xpath, name string, value []byte) {
+ if v.ReadOnly {
+ return
+ }
+
+ spath := strings.Split(xpath, "/")
+ if len(spath) == 0 {
+ return
+ }
+ err := v.db.Update(func(tx *bolt.Tx) error {
+ buckt, err := tx.CreateBucketIfNotExists([]byte(spath[0]))
+ if err != nil {
+ return err
+ }
+
+ for i, p := range spath {
+ if i == 0 {
+ continue
+ }
+ buckt, err = buckt.CreateBucketIfNotExists([]byte(p))
+ if err != nil {
+ return err
+ }
+ }
+
+ return buckt.Put([]byte(name), value)
+ })
+
+ if err != nil {
+ log.TLogln("Error put sets", xpath+"/"+name, ", error:", err)
+ log.TLogln("value:", value)
+ }
+
+ return
+}
+
+func (v *TDB) List(xpath string) []string {
+ spath := strings.Split(xpath, "/")
+ if len(spath) == 0 {
+ return nil
+ }
+ var ret []string
+ err := v.db.View(func(tx *bolt.Tx) error {
+ buckt := tx.Bucket([]byte(spath[0]))
+ if buckt == nil {
+ return nil
+ }
+
+ for i, p := range spath {
+ if i == 0 {
+ continue
+ }
+ buckt = buckt.Bucket([]byte(p))
+ if buckt == nil {
+ return nil
+ }
+ }
+
+ buckt.ForEach(func(_, v []byte) error {
+ if len(v) > 0 {
+ ret = append(ret, string(v))
+ }
+ return nil
+ })
+
+ return nil
+ })
+
+ if err != nil {
+ log.TLogln("Error list sets", xpath, ", error:", err)
+ }
+
+ return ret
+}
+
+func (v *TDB) Rem(xpath, name string) {
+ if v.ReadOnly {
+ return
+ }
+
+ spath := strings.Split(xpath, "/")
+ if len(spath) == 0 {
+ return
+ }
+ err := v.db.Update(func(tx *bolt.Tx) error {
+ buckt := tx.Bucket([]byte(spath[0]))
+ if buckt == nil {
+ return nil
+ }
+
+ for i, p := range spath {
+ if i == 0 {
+ continue
+ }
+ buckt = buckt.Bucket([]byte(p))
+ if buckt == nil {
+ return nil
+ }
+ }
+
+ return buckt.Delete([]byte(name))
+ })
+
+ if err != nil {
+ log.TLogln("Error rem sets", xpath+"/"+name, ", error:", err)
+ }
+
+ return
+}
diff --git a/src/server/settings/settings.go b/src/server/settings/settings.go
new file mode 100644
index 0000000..25ba802
--- /dev/null
+++ b/src/server/settings/settings.go
@@ -0,0 +1,16 @@
+package settings
+
+var (
+ tdb *TDB
+ Path string
+)
+
+func InitSets(path string, readOnly bool) {
+ Path = path
+ tdb = NewTDB(path, readOnly)
+ loadBTSets()
+}
+
+func CloseDB() {
+ tdb.CloseDB()
+}
diff --git a/src/server/settings/torrbt.go b/src/server/settings/torrbt.go
new file mode 100644
index 0000000..040c823
--- /dev/null
+++ b/src/server/settings/torrbt.go
@@ -0,0 +1,77 @@
+package settings
+
+import (
+ "encoding/json"
+
+ "server/log"
+)
+
+type BTSets struct {
+ CacheSize int64 // in byte, def 200 mb
+ PreloadBufferSize int64 // in byte, buffer for preload
+
+ SaveOnDisk bool // save on disk?
+ ContentPath string // path to save content
+
+ RetrackersMode int // 0 - don`t add, 1 - add retrackers (def), 2 - remove retrackers 3 - replace retrackers
+ TorrentDisconnectTimeout int // in seconds
+ EnableDebug bool // print logs
+
+ // BT Config
+ EnableIPv6 bool
+ DisableTCP bool
+ DisableUTP bool
+ DisableUPNP bool
+ DisableDHT bool
+ DisableUpload bool
+ Encryption int // ???? 0 - Enable, 1 - disable, 2 - force
+ DownloadRateLimit int // in kb, 0 - inf
+ UploadRateLimit int // in kb, 0 - inf
+ ConnectionsLimit int
+ DhtConnectionLimit int // 0 - inf
+ PeersListenPort int
+}
+
+func (v *BTSets) String() string {
+ buf, _ := json.Marshal(v)
+ return string(buf)
+}
+
+var (
+ BTsets = loadBTSets()
+)
+
+func SetBTSets(sets *BTSets) {
+ if tdb.ReadOnly {
+ return
+ }
+ BTsets = sets
+ buf, err := json.Marshal(BTsets)
+ if err != nil {
+ log.TLogln("Error marshal btsets", err)
+ return
+ }
+ tdb.Set("Settings", "BitTorr", buf)
+}
+
+func loadBTSets() *BTSets {
+ buf := tdb.Get("Settings", "BitTorr")
+ if len(buf) > 0 {
+ err := json.Unmarshal(buf, &BTsets)
+ if err == nil {
+ return BTsets
+ }
+ log.TLogln("Error unmarshal btsets", err)
+ }
+
+ sets := new(BTSets)
+ sets.EnableDebug = false
+
+ sets.CacheSize = 200 * 1024 * 1024 // 200mb
+ sets.PreloadBufferSize = 20 * 1024 * 1024
+ sets.ConnectionsLimit = 20
+ sets.DhtConnectionLimit = 500
+ sets.RetrackersMode = 1
+ sets.TorrentDisconnectTimeout = 30
+ return sets
+}
diff --git a/src/server/torr/BTServer.go b/src/server/torr/BTServer.go
deleted file mode 100644
index f19f013..0000000
--- a/src/server/torr/BTServer.go
+++ /dev/null
@@ -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)
-}
diff --git a/src/server/torr/Play.go b/src/server/torr/Play.go
deleted file mode 100644
index 8d5061a..0000000
--- a/src/server/torr/Play.go
+++ /dev/null
@@ -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)
-}
diff --git a/src/server/torr/State.go b/src/server/torr/State.go
deleted file mode 100644
index 530644d..0000000
--- a/src/server/torr/State.go
+++ /dev/null
@@ -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
-}
diff --git a/src/server/torr/btserver.go b/src/server/torr/btserver.go
new file mode 100644
index 0000000..8912ab8
--- /dev/null
+++ b/src/server/torr/btserver.go
@@ -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()
+ }
+}
diff --git a/src/server/torr/reader/Reader.go b/src/server/torr/reader/reader.go
similarity index 79%
rename from src/server/torr/reader/Reader.go
rename to src/server/torr/reader/reader.go
index 3833eef..dfcd325 100644
--- a/src/server/torr/reader/Reader.go
+++ b/src/server/torr/reader/reader.go
@@ -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
}
diff --git a/src/server/torr/state.go b/src/server/torr/state.go
new file mode 100644
index 0000000..6dc225e
--- /dev/null
+++ b/src/server/torr/state.go
@@ -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
+}
diff --git a/src/server/torr/storage/filecache/Cache.go b/src/server/torr/storage/filecache/Cache.go
deleted file mode 100644
index c3381cd..0000000
--- a/src/server/torr/storage/filecache/Cache.go
+++ /dev/null
@@ -1 +0,0 @@
-package filecache
diff --git a/src/server/torr/storage/filecache/Storage.go b/src/server/torr/storage/filecache/Storage.go
deleted file mode 100644
index 60f65e0..0000000
--- a/src/server/torr/storage/filecache/Storage.go
+++ /dev/null
@@ -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
-}
diff --git a/src/server/torr/storage/state/state.go b/src/server/torr/storage/state/state.go
deleted file mode 100644
index 1ec9680..0000000
--- a/src/server/torr/storage/state/state.go
+++ /dev/null
@@ -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
-}
diff --git a/src/server/torr/storage/Storage.go b/src/server/torr/storage/storage.go
similarity index 70%
rename from src/server/torr/storage/Storage.go
rename to src/server/torr/storage/storage.go
index e80cc3a..87dfbd5 100644
--- a/src/server/torr/storage/Storage.go
+++ b/src/server/torr/storage/storage.go
@@ -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)
}
diff --git a/src/server/torr/storage/memcache/Buffer.go b/src/server/torr/storage/torrstor/buffer.go
similarity index 94%
rename from src/server/torr/storage/memcache/Buffer.go
rename to src/server/torr/storage/torrstor/buffer.go
index b63111d..adf1c55 100644
--- a/src/server/torr/storage/memcache/Buffer.go
+++ b/src/server/torr/storage/torrstor/buffer.go
@@ -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
}
}
diff --git a/src/server/torr/storage/memcache/Cache.go b/src/server/torr/storage/torrstor/cache.go
similarity index 85%
rename from src/server/torr/storage/memcache/Cache.go
rename to src/server/torr/storage/torrstor/cache.go
index b6c98c7..58cfbfa 100644
--- a/src/server/torr/storage/memcache/Cache.go
+++ b/src/server/torr/storage/torrstor/cache.go
@@ -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 {
diff --git a/src/server/torr/storage/memcache/Piece.go b/src/server/torr/storage/torrstor/piece.go
similarity index 88%
rename from src/server/torr/storage/memcache/Piece.go
rename to src/server/torr/storage/torrstor/piece.go
index f21f75b..e829d2f 100644
--- a/src/server/torr/storage/memcache/Piece.go
+++ b/src/server/torr/storage/torrstor/piece.go
@@ -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
}
diff --git a/src/server/torr/storage/memcache/Storage.go b/src/server/torr/storage/torrstor/storage.go
similarity index 83%
rename from src/server/torr/storage/memcache/Storage.go
rename to src/server/torr/storage/torrstor/storage.go
index 2a54fff..e44a836 100644
--- a/src/server/torr/storage/memcache/Storage.go
+++ b/src/server/torr/storage/torrstor/storage.go
@@ -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
diff --git a/src/server/torr/stream.go b/src/server/torr/stream.go
new file mode 100644
index 0000000..03de85f
--- /dev/null
+++ b/src/server/torr/stream.go
@@ -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
+}
diff --git a/src/server/torr/Torrent.go b/src/server/torr/torrent.go
similarity index 63%
rename from src/server/torr/Torrent.go
rename to src/server/torr/torrent.go
index 51efd6a..d19dfc0 100644
--- a/src/server/torr/Torrent.go
+++ b/src/server/torr/torrent.go
@@ -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
-}
diff --git a/src/server/utils/BlockedIP.go b/src/server/torr/utils/blockedIP.go
similarity index 100%
rename from src/server/utils/BlockedIP.go
rename to src/server/torr/utils/blockedIP.go
diff --git a/src/server/torr/utils/freemem.go b/src/server/torr/utils/freemem.go
new file mode 100644
index 0000000..00b6a1e
--- /dev/null
+++ b/src/server/torr/utils/freemem.go
@@ -0,0 +1,15 @@
+package utils
+
+import (
+ "runtime"
+ "runtime/debug"
+)
+
+func FreeOSMem() {
+ debug.FreeOSMemory()
+}
+
+func FreeOSMemGC() {
+ runtime.GC()
+ debug.FreeOSMemory()
+}
diff --git a/src/server/utils/Torrent.go b/src/server/torr/utils/torrent.go
similarity index 78%
rename from src/server/utils/Torrent.go
rename to src/server/torr/utils/torrent.go
index e42804f..e7ac494 100644
--- a/src/server/utils/Torrent.go
+++ b/src/server/torr/utils/torrent.go
@@ -2,16 +2,11 @@ package utils
import (
"encoding/base32"
- "errors"
"io/ioutil"
"math/rand"
"net/http"
"strings"
- "time"
- "server/settings"
-
- "github.com/anacrolix/torrent"
"golang.org/x/time/rate"
)
@@ -95,30 +90,6 @@ func PeerIDRandom(peer string) string {
return peer + base32.StdEncoding.EncodeToString(randomBytes)[:20-len(peer)]
}
-func GotInfo(t *torrent.Torrent, timeout int) error {
- gi := t.GotInfo()
- select {
- case <-gi:
- return nil
- case <-time.Tick(time.Second * time.Duration(timeout)):
- return errors.New("timeout load torrent info")
- }
-}
-
-func GetReadahead() int64 {
- readahead := settings.Get().CacheSize - (138412032) //132mb
- if readahead < 69206016 { //66mb
- readahead = int64(float64(settings.Get().CacheSize) * 0.33)
- if readahead < 66*1024*1024 {
- readahead = int64(settings.Get().CacheSize)
- if readahead > 66*1024*1024 {
- readahead = 66 * 1024 * 1024
- }
- }
- }
- return readahead
-}
-
func Limit(i int) *rate.Limiter {
l := rate.NewLimiter(rate.Inf, 0)
if i > 0 {
diff --git a/src/server/utils/Prallel.go b/src/server/utils/prallel.go
similarity index 100%
rename from src/server/utils/Prallel.go
rename to src/server/utils/prallel.go
diff --git a/src/server/utils/Utils.go b/src/server/utils/strings.go
similarity index 76%
rename from src/server/utils/Utils.go
rename to src/server/utils/strings.go
index 86937eb..929ef40 100644
--- a/src/server/utils/Utils.go
+++ b/src/server/utils/strings.go
@@ -3,8 +3,6 @@ package utils
import (
"fmt"
"regexp"
- "runtime"
- "runtime/debug"
"strconv"
"strings"
)
@@ -18,15 +16,6 @@ func CleanFName(file string) string {
return ret
}
-func FreeOSMem() {
- debug.FreeOSMemory()
-}
-
-func FreeOSMemGC() {
- runtime.GC()
- debug.FreeOSMemory()
-}
-
const (
_ = 1.0 << (10 * iota) // ignore first value by assigning to blank identifier
KB
@@ -68,13 +57,3 @@ func Format(b float64) string {
return fmt.Sprintf("%.2f%s", value, multiple)
}
-
-//
-//func IsCyrillic(str string) bool {
-// for _, r := range str {
-// if unicode.Is(unicode.Cyrillic, r) {
-// return true
-// }
-// }
-// return false
-//}
diff --git a/src/server/version/Version.go b/src/server/version/Version.go
deleted file mode 100644
index a72a189..0000000
--- a/src/server/version/Version.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package version
-
-const Version = "1.1.77"
-const VerInt = 77
diff --git a/src/server/version/version.go b/src/server/version/version.go
new file mode 100644
index 0000000..9cf13c4
--- /dev/null
+++ b/src/server/version/version.go
@@ -0,0 +1,4 @@
+package version
+
+const Version = "1.2.78"
+const VerInt = 78
diff --git a/src/server/web/About.go b/src/server/web/About.go
deleted file mode 100644
index 222e5d0..0000000
--- a/src/server/web/About.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package server
-
-import (
- "net/http"
-
- "github.com/labstack/echo"
-)
-
-func initAbout(e *echo.Echo) {
- e.GET("/about", aboutPage)
-}
-
-func aboutPage(c echo.Context) error {
- return c.Render(http.StatusOK, "aboutPage", nil)
-}
diff --git a/src/server/web/Info.go b/src/server/web/Info.go
deleted file mode 100644
index 3db7b1e..0000000
--- a/src/server/web/Info.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package server
-
-import (
- "fmt"
- "net/http"
- "sort"
-
- "server/utils"
-
- "github.com/anacrolix/torrent/metainfo"
- "github.com/labstack/echo"
- "github.com/labstack/gommon/bytes"
-)
-
-func initInfo(e *echo.Echo) {
- server.GET("/cache", cachePage)
- server.GET("/stat", statePage)
- server.GET("/btstat", btStatePage)
-}
-
-func btStatePage(c echo.Context) error {
- bts.WriteState(c.Response())
- return c.NoContent(http.StatusOK)
-}
-
-func cachePage(c echo.Context) error {
- return c.Render(http.StatusOK, "cachePage", nil)
-}
-
-func statePage(c echo.Context) error {
- state := bts.BTState()
-
- msg := ""
-
- msg += fmt.Sprintf("Listen port: %d
\n", state.LocalPort)
- msg += fmt.Sprintf("Peer ID: %+q
\n", state.PeerID)
- msg += fmt.Sprintf("Banned IPs: %d
\n", state.BannedIPs)
-
- for _, dht := range state.DHTs {
- msg += fmt.Sprintf("%s DHT server at %s:
\n", dht.Addr().Network(), dht.Addr().String())
- dhtStats := dht.Stats()
- msg += fmt.Sprintf("\t # Nodes: %d (%d good, %d banned)
\n", dhtStats.Nodes, dhtStats.GoodNodes, dhtStats.BadNodes)
- msg += fmt.Sprintf("\t Server ID: %x
\n", dht.ID())
- msg += fmt.Sprintf("\t Announces: %d
\n", dhtStats.SuccessfulOutboundAnnouncePeerQueries)
- msg += fmt.Sprintf("\t Outstanding transactions: %d
\n", dhtStats.OutstandingTransactions)
- }
-
- sort.Slice(state.Torrents, func(i, j int) bool {
- return state.Torrents[i].Hash().HexString() < state.Torrents[j].Hash().HexString()
- })
- msg += "Torrents:
\n"
- for _, t := range state.Torrents {
- st := t.Stats()
- msg += fmt.Sprintf("Name: %v
\n", st.Name)
- msg += fmt.Sprintf("Hash: %v
\n", st.Hash)
- msg += fmt.Sprintf("Status: %v
\n", st.TorrentStatus)
- msg += fmt.Sprintf("Loaded Size: %v
\n", bytes.Format(st.LoadedSize))
- msg += fmt.Sprintf("Torrent Size: %v
\n
\n", bytes.Format(st.TorrentSize))
-
- msg += fmt.Sprintf("Preloaded Bytes: %v
\n", bytes.Format(st.PreloadedBytes))
- msg += fmt.Sprintf("Preload Size: %v
\n
\n", bytes.Format(st.PreloadSize))
-
- msg += fmt.Sprintf("Download Speed: %v/Sec
\n", utils.Format(st.DownloadSpeed))
- msg += fmt.Sprintf("Upload Speed: %v/Sec
\n
\n", utils.Format(st.UploadSpeed))
-
- msg += fmt.Sprintf("\t TotalPeers: %v
\n", st.TotalPeers)
- msg += fmt.Sprintf("\t PendingPeers: %v
\n", st.PendingPeers)
- msg += fmt.Sprintf("\t ActivePeers: %v
\n", st.ActivePeers)
- msg += fmt.Sprintf("\t ConnectedSeeders: %v
\n", st.ConnectedSeeders)
- msg += fmt.Sprintf("\t HalfOpenPeers: %v
\n", st.HalfOpenPeers)
-
- msg += fmt.Sprintf("\t BytesWritten: %v (%v)
\n", st.BytesWritten, bytes.Format(st.BytesWritten))
- msg += fmt.Sprintf("\t BytesWrittenData: %v (%v)
\n", st.BytesWrittenData, bytes.Format(st.BytesWrittenData))
- msg += fmt.Sprintf("\t BytesRead: %v (%v)
\n", st.BytesRead, bytes.Format(st.BytesRead))
- msg += fmt.Sprintf("\t BytesReadData: %v (%v)
\n", st.BytesReadData, bytes.Format(st.BytesReadData))
- msg += fmt.Sprintf("\t BytesReadUsefulData: %v (%v)
\n", st.BytesReadUsefulData, bytes.Format(st.BytesReadUsefulData))
- msg += fmt.Sprintf("\t ChunksWritten: %v
\n", st.ChunksWritten)
- msg += fmt.Sprintf("\t ChunksRead: %v
\n", st.ChunksRead)
- msg += fmt.Sprintf("\t ChunksReadUseful: %v
\n", st.ChunksReadUseful)
- msg += fmt.Sprintf("\t ChunksReadWasted: %v
\n", st.ChunksReadWasted)
- msg += fmt.Sprintf("\t PiecesDirtiedGood: %v
\n", st.PiecesDirtiedGood)
- msg += fmt.Sprintf("\t PiecesDirtiedBad: %v
\n
\n", st.PiecesDirtiedBad)
- if len(st.FileStats) > 0 {
- msg += fmt.Sprintf("\t Files:
\n")
- for _, f := range st.FileStats {
- msg += fmt.Sprintf("\t \t %v Size:%v
\n", f.Path, bytes.Format(f.Length))
- }
- }
-
- hash := metainfo.NewHashFromHex(st.Hash)
- cState := bts.CacheState(hash)
- if cState != nil {
- msg += fmt.Sprintf("CacheType:
\n")
- msg += fmt.Sprintf("Capacity: %v
\n", bytes.Format(cState.Capacity))
- msg += fmt.Sprintf("Filled: %v
\n", bytes.Format(cState.Filled))
- msg += fmt.Sprintf("PiecesLength: %v
\n", bytes.Format(cState.PiecesLength))
- msg += fmt.Sprintf("PiecesCount: %v
\n", cState.PiecesCount)
- for _, p := range cState.Pieces {
- msg += fmt.Sprintf("\t Piece: %v\t Access: %v\t Buffer size: %d(%s)\t Complete: %v\t Hash: %s\n
", p.Id, p.Accessed, p.BufferSize, bytes.Format(int64(p.BufferSize)), p.Completed, p.Hash)
- }
- }
- msg += "
\n\n"
- }
- //msg += `
- //
- //
- //`
- return c.HTML(http.StatusOK, msg)
-}
diff --git a/src/server/web/Server.go b/src/server/web/Server.go
deleted file mode 100644
index a789bc8..0000000
--- a/src/server/web/Server.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package server
-
-import (
- "fmt"
- "log"
- "net"
- "net/http"
- "os"
- "runtime"
- "sync"
- "time"
-
- "server/settings"
- "server/torr"
- "server/version"
- "server/web/mods"
- "server/web/templates"
-
- "github.com/labstack/echo"
- "github.com/labstack/echo/middleware"
-)
-
-var (
- server *echo.Echo
- bts *torr.BTServer
-
- mutex sync.Mutex
- fnMutex sync.Mutex
- err error
-)
-
-func Start(port string) {
- runtime.GOMAXPROCS(runtime.NumCPU())
-
- fmt.Println("Start web server, version:", version.Version)
-
- bts = torr.NewBTS()
- err := bts.Connect()
- if err != nil {
- fmt.Println("Error start torrent client:", err)
- return
- }
-
- mutex.Lock()
- server = echo.New()
- server.HideBanner = true
- server.HidePort = true
- server.HTTPErrorHandler = HTTPErrorHandler
-
- //server.Use(middleware.Logger())
- server.Use(middleware.Recover())
- server.Use(ServerHeaderSet)
-
- templates.InitTemplate(server)
- initTorrent(server)
- initSettings(server)
- initInfo(server)
- initAbout(server)
- mods.InitMods(server)
-
- server.GET("/", mainPage)
- server.GET("/echo", echoPage)
- server.POST("/shutdown", shutdownPage)
- server.GET("/js/api.js", templates.ApiJS)
-
- go func() {
- defer mutex.Unlock()
-
- server.Listener, err = net.Listen("tcp", "0.0.0.0:"+port)
- if err == nil {
- err = server.Start("0.0.0.0:" + port)
- }
- server = nil
- if err != nil {
- fmt.Println("Error start web server:", err)
- }
- }()
-}
-
-func Stop() {
- fnMutex.Lock()
- defer fnMutex.Unlock()
- if server != nil {
- fmt.Println("Stop web server")
- server.Close()
- server = nil
- if bts != nil {
- bts.Disconnect()
- bts = nil
- }
- }
-}
-
-func Wait() error {
- mutex.Lock()
- mutex.Unlock()
- return err
-}
-
-func mainPage(c echo.Context) error {
- return c.Render(http.StatusOK, "mainPage", nil)
-}
-
-func echoPage(c echo.Context) error {
- return c.String(http.StatusOK, version.Version)
-}
-
-func shutdownPage(c echo.Context) error {
- go func() {
- Stop()
- settings.CloseDB()
- time.Sleep(time.Second * 2)
- os.Exit(5)
- }()
- return c.NoContent(http.StatusOK)
-}
-
-func ServerHeaderSet(next echo.HandlerFunc) echo.HandlerFunc {
- return func(c echo.Context) error {
- c.Response().Header().Set("Access-Control-Allow-Origin", "*")
- return next(c)
- }
-}
-
-func HTTPErrorHandler(err error, c echo.Context) {
- var (
- code = http.StatusInternalServerError
- msg interface{}
- )
-
- if he, ok := err.(*echo.HTTPError); ok {
- code = he.Code
- msg = he.Message
- if he.Internal != nil {
- msg = fmt.Sprintf("%v, %v", err, he.Internal)
- }
- } else {
- msg = http.StatusText(code)
- }
- if _, ok := msg.(string); ok {
- msg = echo.Map{"message": msg}
- }
-
- if code != 404 && c.Request().URL.Path != "/torrent/stat" {
- log.Println("Web server error:", err, c.Request().URL)
- }
-
- // Send response
- if !c.Response().Committed {
- if c.Request().Method == echo.HEAD { // Issue #608
- err = c.NoContent(code)
- } else {
- err = c.JSON(code, msg)
- }
- if err != nil {
- c.Logger().Error(err)
- }
- }
-}
diff --git a/src/server/web/Settings.go b/src/server/web/Settings.go
deleted file mode 100644
index 32dfc6a..0000000
--- a/src/server/web/Settings.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package server
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
-
- "server/settings"
-
- "github.com/labstack/echo"
-)
-
-func initSettings(e *echo.Echo) {
- e.GET("/settings", settingsPage)
- e.POST("/settings/read", settingsRead)
- e.POST("/settings/write", settingsWrite)
-}
-
-func settingsPage(c echo.Context) error {
- return c.Render(http.StatusOK, "settingsPage", nil)
-}
-
-func settingsRead(c echo.Context) error {
- return c.JSON(http.StatusOK, settings.Get())
-}
-
-func settingsWrite(c echo.Context) error {
- err := getJsSettings(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- settings.SaveSettings()
- return c.JSON(http.StatusOK, "Ok")
-}
-
-func getJsSettings(c echo.Context) error {
- buf, _ := ioutil.ReadAll(c.Request().Body)
- decoder := json.NewDecoder(bytes.NewBuffer(buf))
- err := decoder.Decode(settings.Get())
- if err != nil {
- if ute, ok := err.(*json.UnmarshalTypeError); ok {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset))
- } else if se, ok := err.(*json.SyntaxError); ok {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error()))
- } else {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- }
- return nil
-}
diff --git a/src/server/web/Torrent.go b/src/server/web/Torrent.go
deleted file mode 100644
index b757793..0000000
--- a/src/server/web/Torrent.go
+++ /dev/null
@@ -1,720 +0,0 @@
-package server
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "net/url"
- "sort"
- "strconv"
- "strings"
- "time"
-
- "server/settings"
- "server/torr"
- "server/utils"
- "server/web/helpers"
-
- "github.com/anacrolix/missinggo/httptoo"
- "github.com/anacrolix/torrent/metainfo"
- "github.com/labstack/echo"
-)
-
-func initTorrent(e *echo.Echo) {
- e.POST("/torrent/add", torrentAdd)
- e.POST("/torrent/upload", torrentUpload)
- e.POST("/torrent/get", torrentGet)
- e.POST("/torrent/rem", torrentRem)
- e.POST("/torrent/list", torrentList)
- e.POST("/torrent/stat", torrentStat)
- e.POST("/torrent/cache", torrentCache)
- e.POST("/torrent/drop", torrentDrop)
-
- e.POST("/torrent/viewed/add", torrentViewedAdd)
- e.POST("/torrent/viewed/remove", torrentViewedRem)
- e.GET("/torrent/viewed/list", torrentViewedList)
-
- e.GET("/torrent/restart", torrentRestart)
-
- e.GET("/torrent/playlist.m3u", torrentPlayListAll)
-
- e.GET("/torrent/play", torrentPlay)
- e.HEAD("/torrent/play", torrentPlay)
- e.GET("/torrent/play/*", torrentPlay)
- e.HEAD("/torrent/play/*", torrentPlay)
-
- e.GET("/torrent/view/:hash/:file", torrentView)
- e.HEAD("/torrent/view/:hash/:file", torrentView)
- e.GET("/torrent/preload/:hash/:file", torrentPreload)
- e.GET("/torrent/preload/:size/:hash/:file", torrentPreloadSize)
-}
-
-type TorrentJsonRequest struct {
- Link string `json:",omitempty"`
- Hash string `json:",omitempty"`
- Title string `json:",omitempty"`
- Info string `json:",omitempty"`
- DontSave bool `json:",omitempty"`
-}
-
-type TorrentJsonResponse struct {
- Name string
- Magnet string
- Hash string
- AddTime int64
- Length int64
- Status torr.TorrentStatus
- Playlist string
- Info string
- Files []TorFile `json:",omitempty"`
-}
-
-type TorFile struct {
- Name string
- Link string
- Play string
- Preload string
- Size int64
- Viewed bool
-}
-
-func torrentAdd(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- if jreq.Link == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Link must be non-empty")
- }
-
- magnet, infoBytes, err := helpers.GetMagnet(jreq.Link)
- if err != nil {
- fmt.Println("Error get magnet:", jreq.Hash, err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- if jreq.Title != "" {
- magnet.DisplayName = jreq.Title
- }
-
- tor := bts.GetTorrent(magnet.InfoHash)
- if tor != nil {
- return c.String(http.StatusOK, magnet.InfoHash.HexString())
- }
-
- torDb, err := settings.LoadTorrentDB(magnet.InfoHash.HexString())
- if err == nil && torDb != nil {
- infoBytes = torDb.InfoBytes
- }
-
- err = helpers.Add(bts, *magnet, infoBytes, !jreq.DontSave)
- if err != nil {
- fmt.Println("Error add torrent:", jreq.Hash, err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- if jreq.Info != "" {
- go func() {
- settings.AddInfo(magnet.InfoHash.HexString(), jreq.Info)
- }()
- }
-
- return c.String(http.StatusOK, magnet.InfoHash.HexString())
-}
-
-func torrentUpload(c echo.Context) error {
- form, err := c.MultipartForm()
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- defer form.RemoveAll()
-
- _, dontSave := form.Value["DontSave"]
- magnets := map[*metainfo.Magnet][]byte{}
-
- for _, file := range form.File {
- torrFile, err := file[0].Open()
- if err != nil {
- return err
- }
- defer torrFile.Close()
-
- mi, err := metainfo.Load(torrFile)
- if err != nil {
- fmt.Println("Error upload torrent", err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- info, err := mi.UnmarshalInfo()
- if err != nil {
- fmt.Println("Error upload torrent", err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- magnet := mi.Magnet(info.Name, mi.HashInfoBytes())
- magnets[&magnet] = mi.InfoBytes
- }
-
- ret := make([]string, 0)
- for magnet, infobytes := range magnets {
- er := helpers.Add(bts, *magnet, infobytes, !dontSave)
- if er != nil {
- err = er
- fmt.Println("Error add torrent:", magnet.String(), er)
- }
- ret = append(ret, magnet.InfoHash.HexString())
- }
-
- return c.JSON(http.StatusOK, ret)
-}
-
-func torrentGet(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- tor, err := settings.LoadTorrentDB(jreq.Hash)
- if err != nil {
- fmt.Println("Error get torrent:", jreq.Hash, err)
- // return echo.NewHTTPError(http.StatusBadRequest, err.Error()) // Handle R/O DB
- }
-
- torrStatus := torr.TorrentAdded
- if tor == nil {
- hash := metainfo.NewHashFromHex(jreq.Hash)
- ts := bts.GetTorrent(hash)
- if ts != nil {
- torrStatus = ts.Status()
- tor = toTorrentDB(ts)
- }
- }
-
- if tor == nil {
- fmt.Println("Error get: torrent not found", jreq.Hash)
- return echo.NewHTTPError(http.StatusBadRequest, "Error get: torrent not found "+jreq.Hash)
- }
-
- js, err := getTorrentJS(tor)
- if err != nil {
- fmt.Println("Error get torrent:", tor.Hash, err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- js.Status = torrStatus
- return c.JSON(http.StatusOK, js)
-}
-
-func torrentRem(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- settings.RemoveTorrentDB(jreq.Hash)
- bts.RemoveTorrent(metainfo.NewHashFromHex(jreq.Hash))
-
- return c.JSON(http.StatusOK, nil)
-}
-
-func torrentList(c echo.Context) error {
- buf, _ := ioutil.ReadAll(c.Request().Body)
- jsstr := string(buf)
- decoder := json.NewDecoder(bytes.NewBufferString(jsstr))
- jsreq := struct {
- Request int
- }{}
- decoder.Decode(&jsreq)
-
- reqType := jsreq.Request
-
- js := make([]TorrentJsonResponse, 0)
- list, _ := settings.LoadTorrentsDB()
-
- for _, tor := range list {
- jsTor, err := getTorrentJS(tor)
- if err != nil {
- fmt.Println("Error get torrent:", err)
- } else {
- js = append(js, *jsTor)
- }
- }
-
- sort.Slice(js, func(i, j int) bool {
- if js[i].AddTime == js[j].AddTime {
- return js[i].Name < js[j].Name
- }
- return js[i].AddTime > js[j].AddTime
- })
-
- slist := bts.List()
-
- find := func(tjs []TorrentJsonResponse, t *torr.Torrent) bool {
- for _, j := range tjs {
- if t.Hash().HexString() == j.Hash {
- return true
- }
- }
- return false
- }
-
- for _, st := range slist {
- if !find(js, st) {
- tdb := toTorrentDB(st)
- jsTor, err := getTorrentJS(tdb)
- if err != nil {
- fmt.Println("Error get torrent:", err)
- } else {
- jsTor.Status = st.Status()
- js = append(js, *jsTor)
- }
- }
- }
-
- if reqType == 1 {
- ret := make([]TorrentJsonResponse, 0)
- for _, r := range js {
- if r.Status == torr.TorrentWorking || len(r.Files) > 0 {
- ret = append(ret, r)
- }
- }
- return c.JSON(http.StatusOK, ret)
- } else if reqType == 2 {
- ret := make([]TorrentJsonResponse, 0)
- for _, r := range js {
- if r.Status == torr.TorrentGettingInfo {
- ret = append(ret, r)
- }
- }
- return c.JSON(http.StatusOK, ret)
- }
-
- return c.JSON(http.StatusOK, js)
-}
-
-func torrentStat(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- hash := metainfo.NewHashFromHex(jreq.Hash)
- tor := bts.GetTorrent(hash)
- if tor == nil {
- return echo.NewHTTPError(http.StatusNotFound)
- }
- stat := tor.Stats()
-
- return c.JSON(http.StatusOK, stat)
-}
-
-func torrentCache(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- hash := metainfo.NewHashFromHex(jreq.Hash)
- stat := bts.CacheState(hash)
- if stat == nil {
- return echo.NewHTTPError(http.StatusNotFound)
- }
-
- return c.JSON(http.StatusOK, stat)
-}
-
-func preload(hashHex, fileLink string, size int64) *echo.HTTPError {
- if size > 0 {
- hash := metainfo.NewHashFromHex(hashHex)
- tor := bts.GetTorrent(hash)
- if tor == nil {
- torrDb, err := settings.LoadTorrentDB(hashHex)
- if err != nil || torrDb == nil {
- return echo.NewHTTPError(http.StatusBadRequest, "Torrent not found: "+hashHex)
- }
- m, err := metainfo.ParseMagnetURI(torrDb.Magnet)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, "Error parser magnet in db: "+hashHex)
- }
- tor, err = bts.AddTorrent(m, torrDb.InfoBytes, nil)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- }
-
- if !tor.WaitInfo() {
- return echo.NewHTTPError(http.StatusBadRequest, "torrent closed befor get info")
- }
-
- file := helpers.FindFileLink(fileLink, tor.Torrent)
- if file == nil {
- return echo.NewHTTPError(http.StatusNotFound, "file in torrent not found: "+fileLink)
- }
- tor.Preload(file, size)
- }
- return nil
-}
-
-func torrentPreload(c echo.Context) error {
- hashHex, err := url.PathUnescape(c.Param("hash"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- fileLink, err := url.PathUnescape(c.Param("file"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- if hashHex == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
- if fileLink == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "File link must be non-empty")
- }
-
- errHttp := preload(hashHex, fileLink, settings.Get().PreloadBufferSize)
- if err != nil {
- return errHttp
- }
-
- return c.NoContent(http.StatusOK)
-}
-
-func torrentPreloadSize(c echo.Context) error {
- hashHex, err := url.PathUnescape(c.Param("hash"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- fileLink, err := url.PathUnescape(c.Param("file"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- szPreload, err := url.PathUnescape(c.Param("size"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- if hashHex == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
- if fileLink == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "File link must be non-empty")
- }
-
- var size = settings.Get().PreloadBufferSize
- if szPreload != "" {
- sz, err := strconv.Atoi(szPreload)
- if err == nil && sz > 0 {
- size = int64(sz) * 1024 * 1024
- }
- }
-
- errHttp := preload(hashHex, fileLink, size)
- if err != nil {
- return errHttp
- }
- //redirectUrl := c.Scheme() + "://" + c.Request().Host + filepath.Join("/torrent/view/", hashHex, fileLink)
- //return c.Redirect(http.StatusFound, redirectUrl)
- return c.NoContent(http.StatusOK)
-}
-
-func torrentDrop(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- bts.RemoveTorrent(metainfo.NewHashFromHex(jreq.Hash))
- return c.NoContent(http.StatusOK)
-}
-
-func torrentViewedAdd(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- err = settings.SetViewed(jreq.Hash)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- return c.NoContent(http.StatusOK)
-}
-
-func torrentViewedRem(c echo.Context) error {
- jreq, err := getJsReqTorr(c)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- if jreq.Hash == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "Hash must be non-empty")
- }
-
- err = settings.RemTorrentViewed(jreq.Hash)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- return c.NoContent(http.StatusOK)
-}
-
-func torrentViewedList(c echo.Context) error {
- err = settings.List(jreq.Hash)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- return c.NoContent(http.StatusOK)
-}
-
-func torrentRestart(c echo.Context) error {
- fmt.Println("Restart torrent engine")
- err := bts.Reconnect()
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- return c.String(http.StatusOK, "Ok")
-}
-
-func torrentPlayListAll(c echo.Context) error {
- list, err := settings.LoadTorrentsDB()
- if err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
-
- m3u := helpers.MakeM3ULists(list, c.Scheme()+"://"+c.Request().Host)
-
- c.Response().Header().Set("Content-Type", "audio/x-mpegurl")
- c.Response().Header().Set("Connection", "close")
- c.Response().Header().Set("Content-Disposition", `attachment; filename="playlist.m3u"`)
- http.ServeContent(c.Response(), c.Request(), "playlist.m3u", time.Now(), bytes.NewReader([]byte(m3u)))
- return c.NoContent(http.StatusOK)
-}
-
-func torrentPlay(c echo.Context) error {
- link := c.QueryParam("link")
- if link == "" {
- return echo.NewHTTPError(http.StatusBadRequest, "link should not be empty")
- }
- if (settings.Get().EnableDebug) {
- fmt.Println("Play:", c.QueryParams()) // mute log flood on play
- }
- qsave := c.QueryParam("save")
- qpreload := c.QueryParam("preload")
- qfile := c.QueryParam("file")
- qstat := c.QueryParam("stat")
- mm3u := c.QueryParam("m3u")
-
- preload := int64(0)
- stat := strings.ToLower(qstat) == "true"
-
- if qpreload != "" {
- preload, _ = strconv.ParseInt(qpreload, 10, 64)
- if preload > 0 {
- preload *= 1024 * 1024
- }
- }
-
- magnet, infoBytes, err := helpers.GetMagnet(link)
- if err != nil {
- fmt.Println("Error get magnet:", link, err)
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- tor := bts.GetTorrent(magnet.InfoHash)
- if tor == nil {
- tor, err = bts.AddTorrent(*magnet, infoBytes, nil)
- if err != nil {
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
- }
- }
-
- if stat {
- return c.JSON(http.StatusOK, getTorPlayState(tor))
- }
-
- if !tor.WaitInfo() {
- return echo.NewHTTPError(http.StatusBadRequest, "torrent closed befor get info")
- }
-
- if strings.ToLower(qsave) == "true" {
- if t, err := settings.LoadTorrentDB(magnet.InfoHash.HexString()); t == nil && err == nil {
- torrDb := toTorrentDB(tor)
- if torrDb != nil {
- torrDb.InfoBytes = infoBytes
- settings.SaveTorrentDB(torrDb)
- }
- }
- }
-
- if strings.ToLower(mm3u) == "true" {
- mt := tor.Torrent.Metainfo()
- m3u := helpers.MakeM3UPlayList(tor.Stats(), mt.Magnet(tor.Name(), tor.Hash()).String(), c.Scheme()+"://"+c.Request().Host)
- c.Response().Header().Set("Content-Type", "audio/x-mpegurl")
- c.Response().Header().Set("Connection", "close")
- name := utils.CleanFName(tor.Name()) + ".m3u"
- c.Response().Header().Set("ETag", httptoo.EncodeQuotedString(fmt.Sprintf("%s/%s", tor.Hash().HexString(), name)))
- c.Response().Header().Set("Content-Disposition", `attachment; filename="`+name+`"`)
- http.ServeContent(c.Response(), c.Request(), name, time.Now(), bytes.NewReader([]byte(m3u)))
- return c.NoContent(http.StatusOK)
- }
-
- files := helpers.GetPlayableFiles(tor.Stats())
-
- if len(files) == 1 {
- file := helpers.FindFile(files[0].Id, tor)
- if file == nil {
- return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprint("File", files[0], "not found in torrent", tor.Name()))
- }
-
- return bts.Play(tor, file, preload, c)
- }
-
- if qfile == "" && len(files) > 1 {
- return c.JSON(http.StatusOK, getTorPlayState(tor))
- }
-
- fileInd, _ := strconv.Atoi(qfile)
- file := helpers.FindFile(fileInd, tor)
- if file == nil {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprint("File index ", fileInd, " not found in torrent ", tor.Name()))
- }
- return bts.Play(tor, file, preload, c)
-}
-
-func torrentView(c echo.Context) error {
- hashHex, err := url.PathUnescape(c.Param("hash"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- fileLink, err := url.PathUnescape(c.Param("file"))
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
-
- hash := metainfo.NewHashFromHex(hashHex)
- tor := bts.GetTorrent(hash)
- if tor == nil {
- torrDb, err := settings.LoadTorrentDB(hashHex)
- if err != nil || torrDb == nil {
- return echo.NewHTTPError(http.StatusBadRequest, "Torrent not found: "+hashHex)
- }
-
- m, err := metainfo.ParseMagnetURI(torrDb.Magnet)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, "Error parser magnet in db: "+hashHex)
- }
-
- tor, err = bts.AddTorrent(m, torrDb.InfoBytes, nil)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- }
-
- if !tor.WaitInfo() {
- return echo.NewHTTPError(http.StatusBadRequest, "torrent closed befor get info")
- }
-
- file := helpers.FindFileLink(fileLink, tor.Torrent)
- if file == nil {
- return echo.NewHTTPError(http.StatusNotFound, "File in torrent not found: "+fileLink)
- }
- return bts.View(tor, file, c)
-}
-
-func toTorrentDB(t *torr.Torrent) *settings.Torrent {
- if t == nil {
- return nil
- }
- tor := new(settings.Torrent)
- tor.Name = t.Name()
- tor.Hash = t.Hash().HexString()
- tor.Timestamp = settings.StartTime.Unix()
- mi := t.Torrent.Metainfo()
- tor.Magnet = mi.Magnet(t.Name(), t.Torrent.InfoHash()).String()
- tor.Size = t.Length()
-
- st := getTorPlayState(t)
-
- for _, f := range st.FileStats {
- tf := settings.File{
- Id: f.Id,
- Name: f.Path,
- Size: f.Length,
- }
- tor.Files = append(tor.Files, tf)
- }
- return tor
-}
-
-func getTorrentJS(tor *settings.Torrent) (*TorrentJsonResponse, error) {
- js := new(TorrentJsonResponse)
- mag, err := metainfo.ParseMagnetURI(tor.Magnet)
- js.Name = tor.Name
- if err == nil && len(tor.Name) < len(mag.DisplayName) {
- js.Name = mag.DisplayName
- }
- mag.Trackers = []string{} // remove retrackers for small link size
- mag.DisplayName = "" // clear dn from link - long query params may fail in QueryParam("link")
- js.Magnet = tor.Magnet
- js.Hash = tor.Hash
- js.AddTime = tor.Timestamp
- js.Length = tor.Size
- js.Playlist = "/torrent/play?link=" + url.QueryEscape(mag.String()) + "&m3u=true"
- var size int64 = 0
- for _, f := range tor.Files {
- size += f.Size
- tf := TorFile{
- Name: f.Name,
- Link: "/torrent/view/" + js.Hash + "/" + utils.CleanFName(f.Name),
- Play: "/torrent/play/" + utils.CleanFName(f.Name) + "?link=" + url.QueryEscape(mag.String()) + "&file=" + fmt.Sprint(f.Id),
- Preload: "/torrent/play/" + utils.CleanFName(f.Name) + "?link=" + url.QueryEscape(mag.String()) + "&file=" + fmt.Sprint(f.Id) + "&preload=true",
- Size: f.Size,
- Viewed: settings.GetViewed(tor.Hash, f.Name),
- }
- js.Files = append(js.Files, tf)
- }
- if tor.Size == 0 {
- js.Length = size
- }
-
- js.Info = settings.GetInfo(tor.Hash)
-
- return js, nil
-}
-
-func getJsReqTorr(c echo.Context) (*TorrentJsonRequest, error) {
- buf, _ := ioutil.ReadAll(c.Request().Body)
- jsstr := string(buf)
- decoder := json.NewDecoder(bytes.NewBufferString(jsstr))
- js := new(TorrentJsonRequest)
- err := decoder.Decode(js)
- if err != nil {
- if ute, ok := err.(*json.UnmarshalTypeError); ok {
- return nil, echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset))
- } else if se, ok := err.(*json.SyntaxError); ok {
- return nil, echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error()))
- } else {
- return nil, echo.NewHTTPError(http.StatusBadRequest, err.Error())
- }
- }
- return js, nil
-}
diff --git a/src/server/web/TorrentState.go b/src/server/web/TorrentState.go
deleted file mode 100644
index fd4c46a..0000000
--- a/src/server/web/TorrentState.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package server
-
-import (
- "server/torr"
- "server/web/helpers"
-)
-
-type TorrentStat struct {
- Name string
- Hash string
-
- TorrentStatus int
- TorrentStatusString string
-
- LoadedSize int64
- TorrentSize int64
-
- PreloadedBytes int64
- PreloadSize int64
-
- DownloadSpeed float64
- UploadSpeed float64
-
- TotalPeers int
- PendingPeers int
- ActivePeers int
- ConnectedSeeders int
-
- FileStats []FileStat
-}
-
-type FileStat struct {
- Id int
- Path string
- Length int64
-}
-
-func getTorPlayState(tor *torr.Torrent) TorrentStat {
- tst := tor.Stats()
- ts := TorrentStat{}
- ts.Name = tst.Name
- ts.Hash = tst.Hash
- ts.TorrentStatus = int(tst.TorrentStatus)
- ts.TorrentStatusString = tst.TorrentStatusString
- ts.LoadedSize = tst.LoadedSize
- ts.TorrentSize = tst.TorrentSize
- ts.PreloadedBytes = tst.PreloadedBytes
- ts.PreloadSize = tst.PreloadSize
- ts.DownloadSpeed = tst.DownloadSpeed
- ts.UploadSpeed = tst.UploadSpeed
- ts.TotalPeers = tst.TotalPeers
- ts.PendingPeers = tst.PendingPeers
- ts.ActivePeers = tst.ActivePeers
- ts.ConnectedSeeders = tst.ConnectedSeeders
-
- files := helpers.GetPlayableFiles(tst)
- ts.FileStats = make([]FileStat, len(files))
- for i, f := range files {
- ts.FileStats[i] = FileStat{
- Id: f.Id,
- Path: f.Path,
- Length: f.Length,
- }
- }
-
- return ts
-}
diff --git a/src/server/web/helpers/Buffer.go b/src/server/web/helpers/Buffer.go
deleted file mode 100644
index 541d946..0000000
--- a/src/server/web/helpers/Buffer.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package helpers
-
-import "bytes"
-
-type SeekingBuffer struct {
- str string
- buffer *bytes.Buffer
- offset int64
- size int64
-}
-
-func NewSeekingBuffer(str string) *SeekingBuffer {
- return &SeekingBuffer{
- str: str,
- buffer: bytes.NewBufferString(str),
- offset: 0,
- }
-}
-
-func (fb *SeekingBuffer) Read(p []byte) (n int, err error) {
- n, err = fb.buffer.Read(p)
- fb.offset += int64(n)
- return n, err
-}
-
-func (fb *SeekingBuffer) Seek(offset int64, whence int) (ret int64, err error) {
- var newoffset int64
- switch whence {
- case 0:
- newoffset = offset
- case 1:
- newoffset = fb.offset + offset
- case 2:
- newoffset = int64(len(fb.str)) - offset
- }
- if newoffset == fb.offset {
- return newoffset, nil
- }
- fb.buffer = bytes.NewBufferString(fb.str[newoffset:])
- fb.offset = newoffset
- return fb.offset, nil
-}
diff --git a/src/server/web/helpers/M3u.go b/src/server/web/helpers/M3u.go
deleted file mode 100644
index d345907..0000000
--- a/src/server/web/helpers/M3u.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package helpers
-
-import (
- "fmt"
- "net/url"
- "path/filepath"
-
- "server/settings"
- "server/torr"
- "server/utils"
-)
-
-func MakeM3ULists(torrents []*settings.Torrent, host string) string {
- m3u := "#EXTM3U\n"
-
- for _, t := range torrents {
- m3u += "#EXTINF:0 type=\"playlist\"," + t.Name + "\n"
-
- magnet := t.Magnet
- mag, _, err := GetMagnet(magnet)
- if err == nil {
- mag.Trackers = []string{} // remove retrackers for small link size
- mag.DisplayName = "" // clear dn from link - long query params may fail in QueryParam("link")
- magnet = mag.String()
- }
- m3u += host + "/torrent/play?link=" + url.QueryEscape(magnet) + "&m3u=true\n"
- }
- return m3u
-}
-
-func MakeM3UPlayList(tor torr.TorrentStats, magnet string, host string) string {
- m3u := "#EXTM3U\n"
-
- mag, _, err := GetMagnet(magnet)
- if err == nil {
- mag.Trackers = []string{} //Remove retrackers for small link size
- mag.DisplayName = "" //Remove dn from link (useless)
- magnet = mag.String()
- }
- magnet = url.QueryEscape(magnet)
-
- for _, f := range tor.FileStats {
- if GetMimeType(f.Path) != "*/*" {
- fn := filepath.Base(f.Path)
- if fn == "" {
- fn = f.Path
- }
- m3u += "#EXTINF:0," + fn + "\n"
- m3u += host + "/torrent/play/" + url.QueryEscape(utils.CleanFName(f.Path)) + "?link=" + magnet + "&file=" + fmt.Sprint(f.Id) + "\n"
- }
- }
- return m3u
-}
diff --git a/src/server/web/helpers/Magnet.go b/src/server/web/helpers/Magnet.go
deleted file mode 100644
index fc8f74a..0000000
--- a/src/server/web/helpers/Magnet.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package helpers
-
-import (
- "errors"
- "fmt"
- "net/http"
- "net/url"
- "runtime"
- "strings"
- "time"
-
- "server/settings"
-
- "github.com/anacrolix/torrent/metainfo"
-)
-
-func GetMagnet(link string) (*metainfo.Magnet, []byte, error) {
- url, err := url.Parse(link)
- if err != nil {
- return nil, nil, err
- }
-
- var mag *metainfo.Magnet
- var infoBytes []byte
- switch strings.ToLower(url.Scheme) {
- case "magnet":
- mag, err = getMag(url.String())
- if err == nil {
- torDb, err := settings.LoadTorrentDB(mag.InfoHash.HexString())
- if err == nil && torDb != nil {
- infoBytes = torDb.InfoBytes
- }
- }
- case "http", "https":
- mag, infoBytes, err = getMagFromHttp(url.String())
- case "":
- mag, err = getMag("magnet:?xt=urn:btih:" + url.Path)
- case "file":
- mag, infoBytes, err = getMagFromFile(url.Path)
- default:
- err = fmt.Errorf("unknown scheme:", url, url.Scheme)
- }
- if err != nil {
- return nil, nil, err
- }
-
- return mag, infoBytes, nil
-}
-
-func getMag(link string) (*metainfo.Magnet, error) {
- mag, err := metainfo.ParseMagnetURI(link)
- return &mag, err
-}
-
-func getMagFromHttp(url string) (*metainfo.Magnet, []byte, error) {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, nil, err
- }
-
- client := new(http.Client)
- client.Timeout = time.Duration(time.Second * 30)
- req.Header.Set("User-Agent", "DWL/1.1.1 (Torrent)")
-
- resp, err := client.Do(req)
- if err != nil {
- return nil, nil, err
- }
- defer resp.Body.Close()
- if resp.StatusCode != 200 {
- return nil, nil, errors.New(resp.Status)
- }
-
- minfo, err := metainfo.Load(resp.Body)
- if err != nil {
- return nil, nil, err
- }
- info, err := minfo.UnmarshalInfo()
- if err != nil {
- return nil, nil, err
- }
- mag := minfo.Magnet(info.Name, minfo.HashInfoBytes())
- return &mag, minfo.InfoBytes, nil
-}
-
-func getMagFromFile(path string) (*metainfo.Magnet, []byte, error) {
- if runtime.GOOS == "windows" && strings.HasPrefix(path, "/") {
- path = strings.TrimPrefix(path, "/")
- }
- minfo, err := metainfo.LoadFromFile(path)
- if err != nil {
- return nil, nil, err
- }
- info, err := minfo.UnmarshalInfo()
- if err != nil {
- return nil, nil, err
- }
-
- mag := minfo.Magnet(info.Name, minfo.HashInfoBytes())
- return &mag, minfo.InfoBytes, nil
-}
diff --git a/src/server/web/helpers/Mime.go b/src/server/web/helpers/Mime.go
deleted file mode 100644
index 4a30efa..0000000
--- a/src/server/web/helpers/Mime.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package helpers
-
-import (
- "path/filepath"
-
- "server/torr"
-)
-
-var extVideo = map[string]interface{}{
- ".3g2": nil,
- ".3gp": nil,
- ".aaf": nil,
- ".asf": nil,
- ".avchd": nil,
- ".avi": nil,
- ".drc": nil,
- ".flv": nil,
- ".m2ts": nil,
- ".ts": nil,
- ".m2v": nil,
- ".m4p": nil,
- ".m4v": nil,
- ".mkv": nil,
- ".mng": nil,
- ".mov": nil,
- ".mp2": nil,
- ".mp4": nil,
- ".mpe": nil,
- ".mpeg": nil,
- ".mpg": nil,
- ".mpv": nil,
- ".mxf": nil,
- ".nsv": nil,
- ".ogg": nil,
- ".ogv": nil,
- ".qt": nil,
- ".rm": nil,
- ".rmvb": nil,
- ".roq": nil,
- ".svi": nil,
- ".vob": nil,
- ".webm": nil,
- ".wmv": nil,
- ".yuv": nil,
-}
-
-var extAudio = map[string]interface{}{
- ".aac": nil,
- ".aiff": nil,
- ".ape": nil,
- ".au": nil,
- ".flac": nil,
- ".gsm": nil,
- ".it": nil,
- ".m3u": nil,
- ".m4a": nil,
- ".mid": nil,
- ".mod": nil,
- ".mp3": nil,
- ".mpa": nil,
- ".pls": nil,
- ".ra": nil,
- ".s3m": nil,
- ".sid": nil,
- ".wav": nil,
- ".wma": nil,
- ".xm": nil,
-}
-
-func GetMimeType(filename string) string {
- ext := filepath.Ext(filename)
- if _, ok := extVideo[ext]; ok {
- return "video/*"
- }
- if _, ok := extAudio[ext]; ok {
- return "audio/*"
- }
- return "*/*"
-}
-
-func GetPlayableFiles(st torr.TorrentStats) []torr.TorrentFileStat {
- files := make([]torr.TorrentFileStat, 0)
- for _, f := range st.FileStats {
- if GetMimeType(f.Path) != "*/*" {
- files = append(files, f)
- }
- }
- return files
-}
diff --git a/src/server/web/helpers/Torrent.go b/src/server/web/helpers/Torrent.go
deleted file mode 100644
index eb90dd7..0000000
--- a/src/server/web/helpers/Torrent.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package helpers
-
-import (
- "fmt"
- "sort"
- "time"
-
- "server/settings"
- "server/torr"
- "server/utils"
-
- "github.com/anacrolix/torrent"
- "github.com/anacrolix/torrent/metainfo"
-)
-
-func Add(bts *torr.BTServer, magnet metainfo.Magnet, infobytes []byte, save bool) error {
- fmt.Println("Adding torrent", magnet.String())
- _, err := bts.AddTorrent(magnet, infobytes, func(torr *torr.Torrent) {
- if torr, _ := settings.LoadTorrentDB(magnet.InfoHash.HexString()); torr != nil {
- return
- }
- torDb := new(settings.Torrent)
- torDb.Name = torr.Name()
- torDb.Hash = torr.Hash().HexString()
- torDb.Size = torr.Length()
- torDb.Magnet = magnet.String()
- torDb.InfoBytes = infobytes
- torDb.Timestamp = time.Now().Unix()
- files := torr.Stats().FileStats
- sort.Slice(files, func(i, j int) bool {
- return files[i].Path < files[j].Path
- })
- for _, f := range files {
- ff := settings.File{
- Id: f.Id,
- Name: f.Path,
- Size: f.Length,
- }
- torDb.Files = append(torDb.Files, ff)
- }
-
- if save {
- err := settings.SaveTorrentDB(torDb)
- if err != nil {
- fmt.Println("Error add torrent to db:", err)
- }
- }
- })
- if err != nil {
- return err
- }
- return nil
-}
-
-func FindFileLink(fileLink string, torr *torrent.Torrent) *torrent.File {
- for _, f := range torr.Files() {
- if utils.CleanFName(f.Path()) == fileLink {
- return f
- }
- }
- return nil
-}
-
-func FindFile(fileInd int, tor *torr.Torrent) *torrent.File {
- files := tor.Files()
- if len(files) == 0 || fileInd < 0 || fileInd >= len(files) {
- return nil
- }
- return files[fileInd]
-}
diff --git a/src/server/web/mods/Mods.go b/src/server/web/mods/Mods.go
deleted file mode 100644
index a9d9e1d..0000000
--- a/src/server/web/mods/Mods.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package mods
-
-import (
- "github.com/labstack/echo"
-)
-
-func InitMods(e *echo.Echo) {
- e.GET("/test", test)
-}
-
-func test(c echo.Context) error {
- return c.HTML(200, `
-
-
-
-
-
-
-
-
-`)
-}
diff --git a/src/server/web/templates/AboutPage.go b/src/server/web/templates/AboutPage.go
deleted file mode 100644
index edebfe7..0000000
--- a/src/server/web/templates/AboutPage.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package templates
-
-import "server/version"
-
-var aboutPage = `
-
-
-
-
-
-
-
-
-
-
-
-
- About
-
-
-
-
-
-

-
TorrServer
-
` + version.Version + `
-
-
Поддержка проекта:
-
PayPal
-
-
Yandex.Деньги
-
-
-
-
-
Инструкция по использованию:
-
4pda.ru
-
Спасибо MadAndron
-
-
-
-
-
Автор:
-
YouROK
-
-
Email:
-
8YouROK8@gmail.com
-
-
Site:
-
GitHub.com/YouROK
-
-
Telegram:
-
@TorrServe
-
-
-
-
-
Спасибо всем, кто тестировал и помогал:
-
kuzzman
-
-
Site:
-
4pda.ru
-
tv-box.pp.ua
-
-
-
MadAndron
-
-
Site:
-
4pda.ru
-
-
-
SpAwN_LMG
-
-
Site:
-
4pda.ru
-
-
-
Zivio
-
-
Site:
-
4pda.ru
-
forum.hdtv.ru
-
-
-
Tw1cker Руслан Пахнев
-
-
Site:
-
4pda.ru
-
GitHub.com/Nemiroff
-
-
-
-
-
-
-`
-
-func (t *Template) parseAboutPage() {
- parsePage(t, "aboutPage", aboutPage)
-}
diff --git a/src/server/web/templates/ApiJS.go b/src/server/web/templates/ApiJS.go
deleted file mode 100644
index 0413a46..0000000
--- a/src/server/web/templates/ApiJS.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package templates
-
-import (
- "net/http"
-
- "server/settings"
- "server/web/helpers"
-
- "github.com/labstack/echo"
-)
-
-var apijs = `
-function addTorrent(link, save, info, done, fail){
- var reqJson = JSON.stringify({ Link: link, Info: info, DontSave: !save});
- $.post('/torrent/add',reqJson)
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function getTorrent(hash, done, fail){
- var reqJson = JSON.stringify({ Hash: hash});
- $.post('/torrent/get',reqJson)
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function removeTorrent(hash, done, fail){
- var reqJson = JSON.stringify({ Hash: hash});
- $.post('/torrent/rem',reqJson)
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function statTorrent(hash, done, fail){
- var reqJson = JSON.stringify({ Hash: hash});
- $.post('/torrent/stat',reqJson)
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function cacheTorrent(hash, done, fail){
- var reqJson = JSON.stringify({ Hash: hash});
- $.post('/torrent/cache',reqJson)
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function listTorrent(done, fail){
- $.post('/torrent/list')
- .done(function( data ) {
- if (done)
- done(data);
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function restartService(done, fail){
- $.get('/torrent/restart')
- .done(function( data ) {
- if (done)
- done();
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function preloadTorrent(preloadLink, done, fail){
- $.get(preloadLink)
- .done(function( data ) {
- if (done)
- done();
- })
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function shutdownServer(fail){
- $.post('/shutdown')
- .fail(function( data ) {
- if (fail)
- fail(data);
- });
-}
-
-function humanizeSize(size) {
- if (typeof size == 'undefined' || size == 0)
- return "";
- var i = Math.floor( Math.log(size) / Math.log(1024) );
- return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
-}
-`
-
-func ApiJS(c echo.Context) error {
- http.ServeContent(c.Response(), c.Request(), "api.js", settings.StartTime, helpers.NewSeekingBuffer(apijs))
- return c.NoContent(http.StatusOK)
-}
diff --git a/src/server/web/templates/CachePage.go b/src/server/web/templates/CachePage.go
deleted file mode 100644
index 841b374..0000000
--- a/src/server/web/templates/CachePage.go
+++ /dev/null
@@ -1,173 +0,0 @@
-package templates
-
-import (
- "server/version"
-)
-
-var cachePage = `
-
-
-
-
-
-
-
-
-
-
-
-
- TorrServer ` + version.Version + `
-
-
-
-
-
-
-
-
-
-
-`
-
-func (t *Template) parseCachePage() {
- parsePage(t, "cachePage", cachePage)
-}
diff --git a/src/server/web/templates/FavIcon.go b/src/server/web/templates/FavIcon.go
deleted file mode 100644
index 13ae5b6..0000000
--- a/src/server/web/templates/FavIcon.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package templates
-
-var faviconB64 = "data:image/png;base64,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"
diff --git a/src/server/web/templates/MainPage.go b/src/server/web/templates/MainPage.go
deleted file mode 100644
index e0629ad..0000000
--- a/src/server/web/templates/MainPage.go
+++ /dev/null
@@ -1,300 +0,0 @@
-package templates
-
-import (
- "server/version"
-)
-
-var mainPage = `
-
-
-
-
-
-
-
-
-
-
-
-
- TorrServer ` + version.Version + `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Торренты:
-
-
-
-
-
-
-
-
-
-
-
-`
-
-func (t *Template) parseMainPage() {
- parsePage(t, "mainPage", mainPage)
-}
diff --git a/src/server/web/templates/SettingsPage.go b/src/server/web/templates/SettingsPage.go
deleted file mode 100644
index 365d6af..0000000
--- a/src/server/web/templates/SettingsPage.go
+++ /dev/null
@@ -1,244 +0,0 @@
-package templates
-
-import "server/version"
-
-var settingsPage = `
-
-
-
-
-
-
-
-
-
-
-
-
-
- TorrServer ` + version.Version + ` Settings
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`
-
-func (t *Template) parseSettingsPage() {
- parsePage(t, "settingsPage", settingsPage)
-}
diff --git a/src/server/web/templates/Template.go b/src/server/web/templates/Template.go
deleted file mode 100644
index 607cfcd..0000000
--- a/src/server/web/templates/Template.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package templates
-
-import (
- "html/template"
- "io"
-
- "github.com/labstack/echo"
-)
-
-type Template struct {
- templates *template.Template
-}
-
-func InitTemplate(e *echo.Echo) {
- temp := new(Template)
-
- temp.parseMainPage()
- temp.parseSettingsPage()
- temp.parseAboutPage()
- temp.parseCachePage()
-
- e.Renderer = temp
-}
-
-func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
- return t.templates.ExecuteTemplate(w, name, data)
-}
-
-func parsePage(temp *Template, name, page string) error {
- s := page
- var tmpl *template.Template
- if temp.templates == nil {
- temp.templates = template.New(name)
- }
- if name == temp.templates.Name() {
- tmpl = temp.templates
- } else {
- tmpl = temp.templates.New(name)
- }
- _, err := tmpl.Parse(s)
- if err != nil {
- return err
- }
- return nil
-}