From ddda39b22a719ec5a091ddc76e59bdb088979ea8 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Sun, 21 Nov 2021 05:03:18 -0800 Subject: [PATCH] Server implementation. (#90) * Server implementation. - Share the content of a folder as a magnet file. - Web interface with all data needed for sharing data. - New configuration to add several servers - Every time the content of the server folder is changed, the magnet file will be generated again. Signed-off-by: Antonio Navarro Perez * Update dependencies Signed-off-by: Antonio Navarro Perez * Use boltdb piece completion storage. Signed-off-by: Antonio Navarro Perez --- assets/js/servers.js | 54 +++++++ assets/templates/routes.html | 9 +- assets/templates/servers.html | 45 ++++++ cmd/distribyted/main.go | 27 +++- config/config.go | 30 ++++ config/model.go | 10 +- go.mod | 7 +- go.sum | 50 +------ http/api.go | 10 ++ http/http.go | 5 +- http/web.go | 6 + templates/config_template.yaml | 35 ++++- templates/navbar.html | 20 +-- templates/servers.html | 47 ++++++ torrent/server.go | 253 +++++++++++++++++++++++++++++++++ 15 files changed, 541 insertions(+), 67 deletions(-) create mode 100644 assets/js/servers.js create mode 100644 assets/templates/servers.html create mode 100644 templates/servers.html create mode 100644 torrent/server.go diff --git a/assets/js/servers.js b/assets/js/servers.js new file mode 100644 index 0000000..f966011 --- /dev/null +++ b/assets/js/servers.js @@ -0,0 +1,54 @@ +Handlebars.registerHelper("to_date", function (timestamp) { + return new Date(timestamp * 1000).toLocaleString() +}); + +Distribyted.servers = { + _template: null, + + _getTemplate: function () { + if (this._template != null) { + return this._template + } + + const tTemplate = fetch('/assets/templates/servers.html') + .then((response) => { + if (response.ok) { + return response.text(); + } else { + Distribyted.message.error('Error getting data from server. Response: ' + response.status); + } + }) + .then((t) => { + return Handlebars.compile(t); + }) + .catch(error => { + Distribyted.message.error('Error getting servers template: ' + error.message); + }); + + this._template = tTemplate; + return tTemplate; + }, + + _getRoutesJson: function () { + return fetch('/api/servers') + .then(function (response) { + if (response.ok) { + return response.json(); + } else { + Distribyted.message.error('Error getting data from server. Response: ' + response.status) + } + }) + .catch(function (error) { + Distribyted.message.error('Error getting status info: ' + error.message) + }); + }, + + loadView: function () { + this._getTemplate() + .then(t => + this._getRoutesJson().then(routes => { + document.getElementById('template_target').innerHTML = t(routes); + }) + ); + } +} \ No newline at end of file diff --git a/assets/templates/routes.html b/assets/templates/routes.html index 1960a93..1a7690e 100644 --- a/assets/templates/routes.html +++ b/assets/templates/routes.html @@ -1,10 +1,9 @@ {{#.}}
-
-
-

{{name}}

+
+

Route: {{name}}

@@ -13,7 +12,7 @@ - + @@ -24,7 +23,7 @@ - + diff --git a/assets/templates/servers.html b/assets/templates/servers.html new file mode 100644 index 0000000..a23e4c7 --- /dev/null +++ b/assets/templates/servers.html @@ -0,0 +1,45 @@ +{{#.}} + +
+
+

{{name}}

+
+
+
+
+
+
+
Server Info:
+

State

+

{{state}}

+

Updated At

+

{{to_date updatedAt}}

+

Seeds: {{seeds}}

+

Peers: {{peers}}

+ +
+
+
+
+
+
+
+
+ + + Magnet URI pointing to the actual folder content. If content + changes, this URI will change too. +
+ +
+ + +
+
+
+
+
+
+
+
+{{/.}} \ No newline at end of file diff --git a/cmd/distribyted/main.go b/cmd/distribyted/main.go index 2952cfe..c282b52 100644 --- a/cmd/distribyted/main.go +++ b/cmd/distribyted/main.go @@ -121,6 +121,25 @@ func load(configPath string, port, webDAVPort int, fuseAllowOther bool) error { return fmt.Errorf("error starting torrent client: %w", err) } + pcp := filepath.Join(conf.Torrent.MetadataFolder, "piece-completion") + if err := os.MkdirAll(pcp, 0744); err != nil { + return fmt.Errorf("error creating piece completion folder: %w", err) + } + + pc, err := storage.NewBoltPieceCompletion(pcp) + if err != nil { + return fmt.Errorf("error creating servers piece completion: %w", err) + } + + var servers []*torrent.Server + for _, s := range conf.Servers { + server := torrent.NewServer(c, pc, s) + servers = append(servers, server) + if err := server.Start(); err != nil { + return fmt.Errorf("error starting server: %w", err) + } + } + cl := loader.NewConfig(conf.Routes) ss := torrent.NewStats() @@ -139,6 +158,12 @@ func load(configPath string, port, webDAVPort int, fuseAllowOther bool) error { go func() { <-sigChan + log.Info().Msg("closing servers...") + for _, s := range servers { + if err := s.Close(); err != nil { + log.Warn().Err(err).Msg("problem closing server") + } + } log.Info().Msg("closing items database...") fis.Close() log.Info().Msg("closing magnet database...") @@ -189,7 +214,7 @@ func load(configPath string, port, webDAVPort int, fuseAllowOther bool) error { logFilename := filepath.Join(conf.Log.Path, dlog.FileName) - err = http.New(fc, ss, ts, ch, port, logFilename) + err = http.New(fc, ss, ts, ch, servers, port, logFilename) log.Error().Err(err).Msg("error initializing HTTP server") return err } diff --git a/config/config.go b/config/config.go index 9ff082f..534dd5e 100644 --- a/config/config.go +++ b/config/config.go @@ -12,6 +12,7 @@ const ( metadataFolder = "./distribyted-data/metadata" mountFolder = "./distribyted-data/mount" logsFolder = "./distribyted-data/logs" + serverFolder = "./distribyted-data/served-folders/server" ) func DefaultConfig() *Root { @@ -60,5 +61,34 @@ func DefaultConfig() *Root { }, }, }, + + Servers: []*Server{ + { + Name: "server", + Path: serverFolder, + Trackers: []string{ + "http://p4p.arenabg.com:1337/announce", + "udp://tracker.opentrackr.org:1337/announce", + "udp://9.rarbg.com:2810/announce", + "udp://open.tracker.cl:1337/announce", + "udp://open.stealth.si:80/announce", + "udp://exodus.desync.com:6969/announce", + "http://openbittorrent.com:80/announce", + "udp://www.torrent.eu.org:451/announce", + "udp://vibe.sleepyinternetfun.xyz:1738/announce", + "udp://udp-tracker.shittyurl.org:6969/announce", + "udp://tracker1.bt.moack.co.kr:80/announce", + "udp://tracker0.ufibox.com:6969/announce", + "udp://tracker.zerobytes.xyz:1337/announce", + "udp://tracker.torrent.eu.org:451/announce", + "udp://tracker.tiny-vps.com:6969/announce", + "udp://tracker.theoks.net:6969/announce", + "udp://tracker.pomf.se:80/announce", + "udp://tracker.moeking.me:6969/announce", + "udp://tracker.leech.ie:1337/announce", + "udp://tracker.altrosky.nl:6969/announce", + }, + }, + }, } } diff --git a/config/model.go b/config/model.go index 51c2356..355cc61 100644 --- a/config/model.go +++ b/config/model.go @@ -8,7 +8,8 @@ type Root struct { Fuse *FuseGlobal `yaml:"fuse"` Log *Log `yaml:"log"` - Routes []*Route `yaml:"routes"` + Routes []*Route `yaml:"routes"` + Servers []*Server `yaml:"servers"` } type Log struct { @@ -46,6 +47,13 @@ type Route struct { Torrents []*Torrent `yaml:"torrents"` } +type Server struct { + Name string `yaml:"name"` + Path string `yaml:"path"` + Trackers []string `yaml:"trackers"` + TrackerURL string `yaml:"tracker_url"` +} + type Torrent struct { MagnetURI string `yaml:"magnet_uri,omitempty"` TorrentPath string `yaml:"torrent_path,omitempty"` diff --git a/go.mod b/go.mod index 54db83a..efadac3 100644 --- a/go.mod +++ b/go.mod @@ -13,12 +13,14 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/dgraph-io/badger/v3 v3.2103.2 github.com/elliotchance/orderedmap v1.4.0 // indirect + github.com/fsnotify/fsnotify v1.5.1 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.7.4 github.com/go-playground/validator/v10 v10.9.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/leodido/go-urn v1.2.1 // indirect + github.com/mattn/go-colorable v0.1.11 github.com/pion/dtls/v2 v2.0.10 // indirect github.com/pion/mdns v0.0.5 // indirect github.com/pion/rtp v1.7.4 // indirect @@ -30,8 +32,9 @@ require ( github.com/urfave/cli/v2 v2.3.0 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 - golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 // indirect + golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) @@ -72,7 +75,6 @@ require ( github.com/huandu/xstrings v1.3.2 // indirect github.com/json-iterator/go v1.1.10 // indirect github.com/klauspost/compress v1.12.3 // indirect - github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect @@ -105,5 +107,4 @@ require ( golang.org/x/text v0.3.6 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect ) diff --git a/go.sum b/go.sum index df03c0d..ef17a34 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ crawshaw.io/sqlite v0.3.2/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4= crawshaw.io/sqlite v0.3.3-0.20210127221821-98b1f83c5508 h1:fILCBBFnjnrQ0whVJlGhfv1E/QiaFDNtGFBObEVRnYg= crawshaw.io/sqlite v0.3.3-0.20210127221821-98b1f83c5508/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -20,16 +21,10 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anacrolix/chansync v0.3.0-0.0.20211007004133-3f72684c4a93 h1:sQ8igc3anitrtKPEHRK+RBvuNZP0+DRAa6jskKlq4+k= -github.com/anacrolix/chansync v0.3.0-0.0.20211007004133-3f72684c4a93/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= github.com/anacrolix/chansync v0.3.0 h1:lRu9tbeuw3wl+PhMu/r+JJCRu5ArFXIluOgdF0ao6/U= github.com/anacrolix/chansync v0.3.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= -github.com/anacrolix/confluence v1.9.0 h1:7WrWktoDw7P4uo1bzgaA8FFesvc7NsTp37sAsG54XlE= -github.com/anacrolix/confluence v1.9.0/go.mod h1:O5uS+WVgip+3SOcV1K7E/jE3m4DtK7Jk6QJTnU2VS5s= github.com/anacrolix/confluence v1.10.0 h1:xXhz98JUXzJ8223pdMRaVPwG7vrpScEzFzmbT30gCc0= github.com/anacrolix/confluence v1.10.0/go.mod h1:dEf1nWBXs0AV9w1u8m/UWugPtzgW2nTL7lYZ2cemA/Q= -github.com/anacrolix/dht/v2 v2.10.6-0.20211101005846-41a76066160f h1:YgcXgfOJhrkrhRpLkv0U4zboPvq0ILchLXblCeGg+Eg= -github.com/anacrolix/dht/v2 v2.10.6-0.20211101005846-41a76066160f/go.mod h1:KA6+NFOtJVU1Ix5aKI3L6kTijMXRjNWbaaVokzDbkt8= github.com/anacrolix/dht/v2 v2.12.1 h1:fvE/JkfDVEHFImsrWCzUsBR/BwyZyLKxZRdUllyAZVU= github.com/anacrolix/dht/v2 v2.12.1/go.mod h1:GfoiqvbDg0um5RVTJYf5HdPLDgk6TQeWKnPDfQ4bmWw= github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= @@ -71,8 +66,6 @@ github.com/anacrolix/sync v0.4.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DC github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8= -github.com/anacrolix/torrent v1.34.1-0.20211028052123-446016cb270c h1:ghnPwLKrQi8Ji2I09cymzp0ZbIQ57sQaWakBmnuWYSM= -github.com/anacrolix/torrent v1.34.1-0.20211028052123-446016cb270c/go.mod h1:eNmTGUF2tnLB4adDjYgx2+hAZhCYW8r8vjF6ZITO2pU= github.com/anacrolix/torrent v1.37.0 h1:a6maknK6S0SkVrUUjgtr+w94XSdRM3xXm5mMpYZYhfg= github.com/anacrolix/torrent v1.37.0/go.mod h1:Z/PwbVgpAthgWLagZoqip84l6XI2NUKr72M+BoF/6vg= github.com/anacrolix/upnp v0.1.2-0.20200416075019-5e9378ed1425 h1:/Wi6l2ONI1FUFWN4cBwHOO90V4ylp4ud/eov6GUcVFk= @@ -89,7 +82,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/billziss-gh/cgofuse v1.5.0 h1:kH516I/s+Ab4diL/Y/ayFeUjjA8ey+JK12xDfBf4HEs= github.com/billziss-gh/cgofuse v1.5.0/go.mod h1:LJjoaUojlVjgo5GQoEJTcJNqZJeRU0nCR84CyxKt2YM= -github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.2.1 h1:M+/hrU9xlMp7t4TyTDQW97d3tRPVuKFC6zBEK16QnXY= github.com/bits-and-blooms/bitset v1.2.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= @@ -99,7 +91,6 @@ github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaq github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -137,6 +128,8 @@ github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9 github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U= @@ -212,7 +205,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -261,7 +253,6 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -292,21 +283,13 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXmf0= -github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ= github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho= github.com/pion/dtls/v2 v2.0.10 h1:wgys7gPR1NMbWjmjJ3CW7lkUGaun8djgH8nahpNLnxI= github.com/pion/dtls/v2 v2.0.10/go.mod h1:00OxfeCRWHShcqT9jx8pKKmBWuTt0NCZoVPCaC4VKvU= -github.com/pion/ice/v2 v2.1.10/go.mod h1:kV4EODVD5ux2z8XncbLHIOtcXKtYXVgLVCeVqnpoeP0= -github.com/pion/ice/v2 v2.1.12 h1:ZDBuZz+fEI7iDifZCYFVzI4p0Foy0YhdSSZ87ZtRcRE= -github.com/pion/ice/v2 v2.1.12/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU= github.com/pion/ice/v2 v2.1.13 h1:/YNYcIw56LT/whwuzkTnrprcRnapj2ZNqUsR0W8elmo= github.com/pion/ice/v2 v2.1.13/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU= -github.com/pion/interceptor v0.0.13/go.mod h1:svsW2QoLHLoGLUr4pDoSopGBEWk8FZwlfxId/OKRKzo= -github.com/pion/interceptor v0.0.15 h1:pQFkBUL8akUHiGoFr+pM94Q/15x7sLFh0K3Nj+DCC6s= -github.com/pion/interceptor v0.0.15/go.mod h1:pg3J253eGi5bqyKzA74+ej5Y19ez2jkWANVnF+Z9Dfk= github.com/pion/interceptor v0.1.0 h1:SlXKaDlEvSl7cr4j8fJykzVz4UdH+7UDtcvx+u01wLU= github.com/pion/interceptor v0.1.0/go.mod h1:j5NIl3tJJPB3u8+Z2Xz8MZs/VV6rc+If9mXEKNuFmEM= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= @@ -315,25 +298,17 @@ github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.6 h1:1zvwBbyd0TeEuuWftrd/4d++m+/kZSeiguxU61LFWpo= github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= github.com/pion/rtcp v1.2.8 h1:Cys8X6r0xxU65ESTmXkqr8eU1Q1Wx+lNkoZCUH4zD7E= github.com/pion/rtcp v1.2.8/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.6.5/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.7.0/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.7.2 h1:HCDKDCixh7PVjkQTsqHAbk1lg+bx059EHxcnyl42dYs= github.com/pion/rtp v1.7.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA= github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.7.10/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0= -github.com/pion/sctp v1.7.12 h1:GsatLufywVruXbZZT1CKg+Jr8ZTkwiPnmUC/oO9+uuY= -github.com/pion/sctp v1.7.12/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= github.com/pion/sctp v1.8.0 h1:6erMF2qmQwXr+0iB1lm0AUSmDr9LdmpaBzgSVAEgehw= github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= github.com/pion/sdp/v3 v3.0.4 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8= github.com/pion/sdp/v3 v3.0.4/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= -github.com/pion/srtp/v2 v2.0.2/go.mod h1:VEyLv4CuxrwGY8cxM+Ng3bmVy8ckz/1t6A0q/msKOw0= github.com/pion/srtp/v2 v2.0.5 h1:ks3wcTvIUE/GHndO3FAvROQ9opy0uLELpwHJaQ1yqhQ= github.com/pion/srtp/v2 v2.0.5/go.mod h1:8k6AJlal740mrZ6WYxc4Dg6qDqqhxoRG2GSjlUhDF0A= github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= @@ -346,8 +321,6 @@ github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA= github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw= github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pion/webrtc/v3 v3.0.32 h1:5J+zNep9am8Swh6kEMp+LaGXNvn6qQWpGkLBnVW44L4= -github.com/pion/webrtc/v3 v3.0.32/go.mod h1:wX3V5dQQUGCifhT1mYftC2kCrDQX6ZJ3B7Yad0R9JK0= github.com/pion/webrtc/v3 v3.1.9 h1:Nyimo16me180ZBT35nV2YcrZvjOs1i4ktUi/UmXVQGg= github.com/pion/webrtc/v3 v3.1.9/go.mod h1:2b1+xQu7GP0vaMGPLbmEX+uB+Fvn2F4sDBp90ZrPBdI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -380,8 +353,6 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs= github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II= -github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI= github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -439,7 +410,6 @@ github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0s github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -455,7 +425,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -488,12 +457,8 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d h1:QWMn1lFvU/nZ58ssWqiFJMd3DKIII8NYc4sn708XgKs= -golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -533,17 +498,14 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211102192858-4dd72447c267 h1:7zYaz3tjChtpayGDzu6H0hDAUM5zIGA2XW7kRNgQ0jc= -golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 h1:7NCfEGl0sfUojmX78nK9pBJuUlSZWEJA/TwASvfiPLo= -golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c h1:DHcbWVXeY+0Y8HHKR+rbLwnoh2F4tNCY7rTiHJ30RmA= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -562,8 +524,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/http/api.go b/http/api.go index e17158c..cd0d885 100644 --- a/http/api.go +++ b/http/api.go @@ -25,6 +25,16 @@ var apiStatusHandler = func(fc *filecache.Cache, ss *torrent.Stats) gin.HandlerF } } +var apiServersHandler = func(ss []*torrent.Server) gin.HandlerFunc { + return func(ctx *gin.Context) { + var infos []*torrent.ServerInfo + for _, s := range ss { + infos = append(infos, s.Info()) + } + ctx.JSON(http.StatusOK, infos) + } +} + var apiRoutesHandler = func(ss *torrent.Stats) gin.HandlerFunc { return func(ctx *gin.Context) { s := ss.RoutesStats() diff --git a/http/http.go b/http/http.go index 2bb0cfe..13e3f77 100644 --- a/http/http.go +++ b/http/http.go @@ -13,7 +13,7 @@ import ( "github.com/shurcooL/httpfs/html/vfstemplate" ) -func New(fc *filecache.Cache, ss *torrent.Stats, s *torrent.Service, ch *config.Handler, port int, logPath string) error { +func New(fc *filecache.Cache, ss *torrent.Stats, s *torrent.Service, ch *config.Handler, tss []*torrent.Server, port int, logPath string) error { gin.SetMode(gin.ReleaseMode) r := gin.New() r.Use(gin.Recovery()) @@ -31,11 +31,14 @@ func New(fc *filecache.Cache, ss *torrent.Stats, s *torrent.Service, ch *config. r.GET("/", indexHandler) r.GET("/routes", routesHandler(ss)) r.GET("/logs", logsHandler) + r.GET("/servers", serversFoldersHandler()) api := r.Group("/api") { api.GET("/log", apiLogHandler(logPath)) api.GET("/status", apiStatusHandler(fc, ss)) + api.GET("/servers", apiServersHandler(tss)) + api.GET("/routes", apiRoutesHandler(ss)) api.POST("/routes/:route/torrent", apiAddTorrentHandler(s)) api.DELETE("/routes/:route/torrent/:torrent_hash", apiDelTorrentHandler(s)) diff --git a/http/web.go b/http/web.go index 2a13f3d..4ba42fb 100644 --- a/http/web.go +++ b/http/web.go @@ -20,3 +20,9 @@ var routesHandler = func(ss *torrent.Stats) gin.HandlerFunc { var logsHandler = func(c *gin.Context) { c.HTML(http.StatusOK, "logs.html", nil) } + +var serversFoldersHandler = func() gin.HandlerFunc { + return func(c *gin.Context) { + c.HTML(http.StatusOK, "servers.html", nil) + } +} diff --git a/templates/config_template.yaml b/templates/config_template.yaml index 16e16c3..45c8b30 100644 --- a/templates/config_template.yaml +++ b/templates/config_template.yaml @@ -71,4 +71,37 @@ routes: # torrents: # - magnet_uri: "magnet:?xt=urn:btih:9dea07ba660a722ae1008c4c8afdd303b6f6e53b&tr=http%3A%2F%2Facademictorrents.com%2Fannounce.php&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969" # - magnet_uri: "magnet:?xt=urn:btih:d8b3a315172c8d804528762f37fa67db14577cdb&tr=http%3A%2F%2Facademictorrents.com%2Fannounce.php&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969" - # - magnet_uri: "magnet:?xt=urn:btih:1e0a00b9c606cf87c03e676f75929463c7756fb5&tr=http%3A%2F%2Facademictorrents.com%2Fannounce.php&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969" \ No newline at end of file + # - magnet_uri: "magnet:?xt=urn:btih:1e0a00b9c606cf87c03e676f75929463c7756fb5&tr=http%3A%2F%2Facademictorrents.com%2Fannounce.php&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969" + +# List of folders where the content will be transformed to a magnet link. You can share any content sending that magnet link to others. +servers: + - name: server + path: ./distribyted-data/served-folders/server + + # Get trackers from web text file. The file will be loaded every time a magnet uri is generated, + # so all trackers will be up to date. + # tracker_url: "https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt" + + # Trackers to be used to announce the served content. If tracker_url is set and it fails, + # this list will be used instead. + trackers: + - "http://p4p.arenabg.com:1337/announce" + - "udp://tracker.opentrackr.org:1337/announce" + - "udp://9.rarbg.com:2810/announce" + - "udp://open.tracker.cl:1337/announce" + - "udp://open.stealth.si:80/announce" + - "udp://exodus.desync.com:6969/announce" + - "http://openbittorrent.com:80/announce" + - "udp://www.torrent.eu.org:451/announce" + - "udp://vibe.sleepyinternetfun.xyz:1738/announce" + - "udp://udp-tracker.shittyurl.org:6969/announce" + - "udp://tracker1.bt.moack.co.kr:80/announce" + - "udp://tracker0.ufibox.com:6969/announce" + - "udp://tracker.zerobytes.xyz:1337/announce" + - "udp://tracker.torrent.eu.org:451/announce" + - "udp://tracker.tiny-vps.com:6969/announce" + - "udp://tracker.theoks.net:6969/announce" + - "udp://tracker.pomf.se:80/announce" + - "udp://tracker.moeking.me:6969/announce" + - "udp://tracker.leech.ie:1337/announce" + - "udp://tracker.altrosky.nl:6969/announce" \ No newline at end of file diff --git a/templates/navbar.html b/templates/navbar.html index abdd264..8f98800 100644 --- a/templates/navbar.html +++ b/templates/navbar.html @@ -37,6 +37,16 @@ Routes + {{if eq . "served-folders"}} +
  • + {{else}} +
  • + {{end}} + + + Served Folders + +
  • {{if eq . "logs"}}
  • {{else}} @@ -47,16 +57,6 @@ Logs
  • - diff --git a/templates/servers.html b/templates/servers.html new file mode 100644 index 0000000..8238f5f --- /dev/null +++ b/templates/servers.html @@ -0,0 +1,47 @@ + + + + {{template "header.html" "Served Folders"}} + + + + +
    + {{template "navbar.html" "served-folders"}} + +
    + + + +
    +
    + +
    +
    + +
    +
    + + {{template "footer.html"}} + + + + + + + \ No newline at end of file diff --git a/torrent/server.go b/torrent/server.go new file mode 100644 index 0000000..8a0ec3b --- /dev/null +++ b/torrent/server.go @@ -0,0 +1,253 @@ +package torrent + +import ( + "fmt" + "os" + "path/filepath" + "sync" + "sync/atomic" + "time" + + "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/bencode" + "github.com/anacrolix/torrent/metainfo" + "github.com/anacrolix/torrent/storage" + "github.com/distribyted/distribyted/config" + "github.com/fsnotify/fsnotify" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +type ServerState int + +const ( + UNKNOWN ServerState = iota + SEEDING + READING + UPDATING + STOPPED + ERROR +) + +func (ss ServerState) String() string { + return [...]string{"Unknown", "Seeding", "Reading", "Updating", "Stopped", "Error"}[ss] +} + +type ServerInfo struct { + Magnet string `json:"magnetUri"` + UpdatedAt int64 `json:"updatedAt"` + Name string `json:"name"` + Folder string `json:"folder"` + State string `json:"state"` + Peers int `json:"peers"` + Seeds int `json:"seeds"` +} + +type Server struct { + cfg *config.Server + log zerolog.Logger + + fw *fsnotify.Watcher + + eventsCount uint64 + + c *torrent.Client + pc storage.PieceCompletion + + mu sync.RWMutex + t *torrent.Torrent + si ServerInfo +} + +func NewServer(c *torrent.Client, pc storage.PieceCompletion, cfg *config.Server) *Server { + l := log.Logger.With().Str("component", "server").Str("name", cfg.Name).Logger() + + return &Server{ + cfg: cfg, + log: l, + c: c, + pc: pc, + } +} + +func (s *Server) Start() error { + s.log.Info().Msg("starting new server folder") + w, err := fsnotify.NewWatcher() + if err != nil { + return err + } + + if err := os.MkdirAll(s.cfg.Path, 0744); err != nil { + return fmt.Errorf("error creating server folder: %s. Error: %w", s.cfg.Path, err) + } + + if err := filepath.Walk(s.cfg.Path, + func(path string, info os.FileInfo, err error) error { + if info.Mode().IsDir() { + s.log.Debug().Str("folder", path).Msg("adding new folder") + return w.Add(path) + } + + return nil + }); err != nil { + return err + } + + s.fw = w + + if err := s.makeMagnet(); err != nil { + return err + } + + go s.watch() + + go func() { + for { + select { + case event, ok := <-w.Events: + if !ok { + return + } + + s.log.Info().Str("file", event.Name).Str("op", event.Op.String()).Msg("file changed inside server folder") + atomic.AddUint64(&s.eventsCount, 1) + case err, ok := <-w.Errors: + if !ok { + return + } + + s.updateState(STOPPED) + s.log.Error().Err(err).Msg("error watching server folder") + } + } + }() + + s.log.Info().Msg("server folder started") + + return nil +} + +func (s *Server) watch() { + s.log.Info().Msg("starting watcher") + for range time.Tick(time.Second * 5) { + if s.eventsCount == 0 { + continue + } + + ec := s.eventsCount + if err := s.makeMagnet(); err != nil { + s.updateState(ERROR) + s.log.Error().Err(err).Msg("error generating magnet") + } + + atomic.AddUint64(&s.eventsCount, -ec) + } +} + +func (s *Server) makeMagnet() error { + + s.log.Info().Msg("starting serving new torrent") + + info := metainfo.Info{ + PieceLength: 1 << 8, + } + + s.updateState(READING) + + if err := info.BuildFromFilePath(s.cfg.Path); err != nil { + return err + } + + s.updateState(UPDATING) + + if len(info.Files) == 0 { + s.mu.Lock() + s.si.Magnet = "" + s.si.Folder = s.cfg.Path + s.si.Name = s.cfg.Name + s.si.UpdatedAt = time.Now().Unix() + s.mu.Unlock() + s.log.Info().Msg("not creating magnet from empty folder") + + s.updateState(STOPPED) + return nil + } + + mi := metainfo.MetaInfo{ + InfoBytes: bencode.MustMarshal(info), + } + + ih := mi.HashInfoBytes() + + to, _ := s.c.AddTorrentOpt(torrent.AddTorrentOpts{ + InfoHash: ih, + Storage: storage.NewFileOpts(storage.NewFileClientOpts{ + ClientBaseDir: s.cfg.Path, + FilePathMaker: func(opts storage.FilePathMakerOpts) string { + return filepath.Join(opts.File.Path...) + }, + TorrentDirMaker: nil, + PieceCompletion: s.pc, + }), + }) + + tks := s.trackers() + + err := to.MergeSpec(&torrent.TorrentSpec{ + InfoBytes: mi.InfoBytes, + + Trackers: [][]string{tks}, + }) + if err != nil { + return err + } + + m := metainfo.Magnet{ + InfoHash: ih, + DisplayName: s.cfg.Name, + Trackers: tks, + } + + s.mu.Lock() + s.t = to + s.si.Magnet = m.String() + s.si.Folder = s.cfg.Path + s.si.Name = s.cfg.Name + s.si.UpdatedAt = time.Now().Unix() + s.mu.Unlock() + s.updateState(SEEDING) + + s.log.Info().Str("hash", ih.HexString()).Msg("new torrent is ready") + + return nil +} + +func (s *Server) updateState(ss ServerState) { + s.mu.Lock() + s.si.State = ss.String() + s.mu.Unlock() +} + +func (s *Server) trackers() []string { + // TODO load trackers from URL too + return s.cfg.Trackers +} + +func (s *Server) Close() error { + if s.fw == nil { + return nil + } + return s.fw.Close() +} + +func (s *Server) Info() *ServerInfo { + s.mu.RLock() + defer s.mu.RUnlock() + if s.t != nil { + st := s.t.Stats() + s.si.Peers = st.TotalPeers + s.si.Seeds = st.ConnectedSeeders + } + + return &s.si +}
    Name / Peers/SeedersPeers/Seeders Status Actions
    {{name}} {{ibytes downloadedBytes timePassed}} / {{ibytes uploadedBytes timePassed}}{{{torrent_info peers seeders pieceSize}}}{{{torrent_info peers seeders pieceSize}}} {{{torrent_status pieceChunks totalPieces}}}