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 <antnavper@gmail.com> * Update dependencies Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com> * Use boltdb piece completion storage. Signed-off-by: Antonio Navarro Perez <antnavper@gmail.com>
This commit is contained in:
parent
5d4e48f0f9
commit
ddda39b22a
15 changed files with 541 additions and 67 deletions
54
assets/js/servers.js
Normal file
54
assets/js/servers.js
Normal file
|
@ -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);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
{{#.}}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<!-- Recent Order Table -->
|
||||
<div class="card card-table-border-none">
|
||||
<div class="card-header justify-content-between">
|
||||
<h2>{{name}}</h2>
|
||||
<div class="card-header justify-content-between card-header-border-bottom">
|
||||
<h2>Route: {{name}}</h2>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-5">
|
||||
<table class="table card-table table-responsive table-responsive-large" style="width:100%">
|
||||
|
@ -13,7 +12,7 @@
|
|||
<th style="width: 30%">Name</th>
|
||||
<th style="width: 15%"><i class="mdi mdi-arrow-down"></i> / <i class="mdi mdi-arrow-up"></i>
|
||||
</th>
|
||||
<th style="width: 15%">Peers/Seeders</th>
|
||||
<th style="width: 15%" class="d-none d-lg-table-cell">Peers/Seeders</th>
|
||||
<th style="width: 35%" class="d-none d-lg-table-cell">Status</th>
|
||||
<th style="width: 5%" >Actions</th>
|
||||
</tr>
|
||||
|
@ -24,7 +23,7 @@
|
|||
<td>{{name}}</td>
|
||||
<td>{{ibytes downloadedBytes timePassed}} / {{ibytes
|
||||
uploadedBytes timePassed}}</td>
|
||||
<td>{{{torrent_info peers seeders pieceSize}}}</td>
|
||||
<td class="d-none d-lg-table-cell">{{{torrent_info peers seeders pieceSize}}}</td>
|
||||
<td class="d-none d-lg-table-cell">
|
||||
{{{torrent_status pieceChunks totalPieces}}}
|
||||
</td>
|
||||
|
|
45
assets/templates/servers.html
Normal file
45
assets/templates/servers.html
Normal file
|
@ -0,0 +1,45 @@
|
|||
{{#.}}
|
||||
|
||||
<div class="card card-default">
|
||||
<div class="card-header justify-content-between align-items-center card-header-border-bottom">
|
||||
<h2>{{name}}</h2>
|
||||
</div>
|
||||
<div class="bg-white border rounded">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="profile-content-left pt-5 pb-3 px-3 px-xl-5">
|
||||
<div class="contact-info pt-4">
|
||||
<h5 class="text-dark mb-1">Server Info:</h5>
|
||||
<p class="text-dark font-weight-medium pt-4 mb-2">State</p>
|
||||
<p>{{state}}</p>
|
||||
<p class="text-dark font-weight-medium pt-4 mb-2">Updated At</p>
|
||||
<p>{{to_date updatedAt}}</p>
|
||||
<p class="text-dark font-weight-medium pt-4 mb-2">Seeds: {{seeds}}</p>
|
||||
<p class="text-dark font-weight-medium pt-4 mb-2">Peers: {{peers}}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8 col-xl-9">
|
||||
<div class="profile-content-right py-5">
|
||||
<div class="tab-content px-3 px-xl-5">
|
||||
<div class="mt-5">
|
||||
<div class="form-group mb-4">
|
||||
<label for="magnetUri">Magnet URI</label>
|
||||
<input type="text" class="form-control" id="magnetUri" value="{{magnetUri}}">
|
||||
<span class="d-block mt-1">Magnet URI pointing to the actual folder content. If content
|
||||
changes, this URI will change too.</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-4">
|
||||
<label for="folder">Folder</label>
|
||||
<input type="folder" class="form-control" id="folder" value="{{folder}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/.}}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ type Root struct {
|
|||
Log *Log `yaml:"log"`
|
||||
|
||||
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"`
|
||||
|
|
7
go.mod
7
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
|
||||
)
|
||||
|
|
50
go.sum
50
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=
|
||||
|
|
10
http/api.go
10
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()
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,3 +72,36 @@ routes:
|
|||
# - 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"
|
||||
|
||||
# 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"
|
|
@ -37,6 +37,16 @@
|
|||
<span class="nav-text">Routes</span>
|
||||
</a>
|
||||
</li>
|
||||
{{if eq . "served-folders"}}
|
||||
<li class="active">
|
||||
{{else}}
|
||||
<li>
|
||||
{{end}}
|
||||
<a class="sidenav-item-link" href="/servers">
|
||||
<i class="mdi mdi-folder-upload-outline"></i>
|
||||
<span class="nav-text">Served Folders</span>
|
||||
</a>
|
||||
</li>
|
||||
{{if eq . "logs"}}
|
||||
<li class="active">
|
||||
{{else}}
|
||||
|
@ -47,16 +57,6 @@
|
|||
<span class="nav-text">Logs</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- {{if eq . "watched-folders"}}
|
||||
<li class="active">
|
||||
{{else}}
|
||||
<li>
|
||||
{{end}}
|
||||
<a class="sidenav-item-link" href="/watched">
|
||||
<i class="mdi mdi-folder-upload-outline"></i>
|
||||
<span class="nav-text">Watched Folders</span>
|
||||
</a>
|
||||
</li> -->
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
|
47
templates/servers.html
Normal file
47
templates/servers.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
{{template "header.html" "Served Folders"}}
|
||||
</head>
|
||||
|
||||
|
||||
<body class="header-fixed sidebar-fixed sidebar-dark header-light" id="body">
|
||||
<div class="wrapper">
|
||||
{{template "navbar.html" "served-folders"}}
|
||||
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<header class="main-header " id="header">
|
||||
<nav class="navbar navbar-static-top navbar-expand-lg">
|
||||
<!-- Sidebar toggle button -->
|
||||
<button id="sidebar-toggler" class="sidebar-toggle">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content" id="template_target">
|
||||
|
||||
</div>
|
||||
<footer class="footer mt-auto">
|
||||
<div class="copyright bg-white">
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{{template "footer.html"}}
|
||||
|
||||
<script src="assets/js/servers.js"></script>
|
||||
<script>
|
||||
Distribyted.servers.loadView();
|
||||
setInterval(function () {
|
||||
Distribyted.servers.loadView();
|
||||
}, 5000)
|
||||
|
||||
</script>
|
||||
<script>
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
253
torrent/server.go
Normal file
253
torrent/server.go
Normal file
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue