remove all private tracker logic
There are no consumers of any of this logic nor is it complete. We're better off without it in the meantime until we have a use case and a more cohesive model for expressing it.
This commit is contained in:
parent
f70be94911
commit
9862a57b73
21 changed files with 24 additions and 516 deletions
|
@ -45,26 +45,19 @@ Limits the number of outstanding requests. Set to `0` to disable.
|
||||||
|
|
||||||
Then listen address for the UDP server. If only a port is specified, the tracker will listen on all interfaces. If left empty, the tracker will not run a UDP endpoint.
|
Then listen address for the UDP server. If only a port is specified, the tracker will listen on all interfaces. If left empty, the tracker will not run a UDP endpoint.
|
||||||
|
|
||||||
##### `privateEnabled`
|
|
||||||
|
|
||||||
type: bool
|
|
||||||
default: true
|
|
||||||
|
|
||||||
Whether this is a public or private tracker.
|
|
||||||
|
|
||||||
##### `createOnAnnounce`
|
##### `createOnAnnounce`
|
||||||
|
|
||||||
type: bool
|
type: bool
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
Whether to register new torrents with the tracker when any client announces (`true`), or to return an error if the torrent doesn't exist (`false`). This should be set to `false` for private trackers in most cases.
|
Whether to register new torrents with the tracker when any client announces (`true`), or to return an error if the torrent doesn't exist (`false`).
|
||||||
|
|
||||||
##### `purgeInactiveTorrents`
|
##### `purgeInactiveTorrents`
|
||||||
|
|
||||||
type: bool
|
type: bool
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
If torrents should be forgotten when there are no active peers. This should be set to `false` for private trackers.
|
If torrents should be forgotten when there are no active peers.
|
||||||
|
|
||||||
##### `announce`
|
##### `announce`
|
||||||
|
|
||||||
|
@ -129,13 +122,6 @@ Enables the peer ID whitelist.
|
||||||
|
|
||||||
List of peer ID prefixes to allow if `client_whitelist_enabled` is set to true.
|
List of peer ID prefixes to allow if `client_whitelist_enabled` is set to true.
|
||||||
|
|
||||||
##### `freeleechEnabled`
|
|
||||||
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
|
|
||||||
For private trackers only, whether download stats should be counted or ignored for users.
|
|
||||||
|
|
||||||
##### `torrentMapShards`
|
##### `torrentMapShards`
|
||||||
|
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -225,4 +211,4 @@ Whether the information about memory should be verbose.
|
||||||
type: duration
|
type: duration
|
||||||
default: "5s"
|
default: "5s"
|
||||||
|
|
||||||
Interval at which to collect statistics about memory.
|
Interval at which to collect statistics about memory.
|
||||||
|
|
|
@ -14,7 +14,6 @@ RUN godep restore
|
||||||
# Add source
|
# Add source
|
||||||
ADD *.go /go/src/github.com/chihaya/chihaya/
|
ADD *.go /go/src/github.com/chihaya/chihaya/
|
||||||
ADD api /go/src/github.com/chihaya/chihaya/api
|
ADD api /go/src/github.com/chihaya/chihaya/api
|
||||||
ADD backend /go/src/github.com/chihaya/chihaya/backend
|
|
||||||
ADD cmd /go/src/github.com/chihaya/chihaya/cmd
|
ADD cmd /go/src/github.com/chihaya/chihaya/cmd
|
||||||
ADD config /go/src/github.com/chihaya/chihaya/config
|
ADD config /go/src/github.com/chihaya/chihaya/config
|
||||||
ADD http /go/src/github.com/chihaya/chihaya/http
|
ADD http /go/src/github.com/chihaya/chihaya/http
|
||||||
|
|
|
@ -84,11 +84,6 @@ func (s *Server) Serve() {
|
||||||
func newRouter(s *Server) *httprouter.Router {
|
func newRouter(s *Server) *httprouter.Router {
|
||||||
r := httprouter.New()
|
r := httprouter.New()
|
||||||
|
|
||||||
if s.config.PrivateEnabled {
|
|
||||||
r.PUT("/users/:passkey", makeHandler(s.putUser))
|
|
||||||
r.DELETE("/users/:passkey", makeHandler(s.delUser))
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.config.ClientWhitelistEnabled {
|
if s.config.ClientWhitelistEnabled {
|
||||||
r.GET("/clients/:clientID", makeHandler(s.getClient))
|
r.GET("/clients/:clientID", makeHandler(s.getClient))
|
||||||
r.PUT("/clients/:clientID", makeHandler(s.putClient))
|
r.PUT("/clients/:clientID", makeHandler(s.putClient))
|
||||||
|
|
|
@ -32,13 +32,6 @@ func handleError(err error) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) check(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
func (s *Server) check(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
||||||
// Attempt to ping the backend if private tracker is enabled.
|
|
||||||
if s.config.PrivateEnabled {
|
|
||||||
if err := s.tracker.Backend.Ping(); err != nil {
|
|
||||||
return handleError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := w.Write([]byte("STILL-ALIVE"))
|
_, err := w.Write([]byte("STILL-ALIVE"))
|
||||||
return handleError(err)
|
return handleError(err)
|
||||||
}
|
}
|
||||||
|
@ -109,35 +102,6 @@ func (s *Server) delTorrent(w http.ResponseWriter, r *http.Request, p httprouter
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
|
||||||
user, err := s.tracker.FindUser(p.ByName("passkey"))
|
|
||||||
if err == models.ErrUserDNE {
|
|
||||||
return http.StatusNotFound, err
|
|
||||||
} else if err != nil {
|
|
||||||
return http.StatusInternalServerError, err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", jsonContentType)
|
|
||||||
e := json.NewEncoder(w)
|
|
||||||
return handleError(e.Encode(user))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) putUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
|
||||||
var user models.User
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&user)
|
|
||||||
if err != nil {
|
|
||||||
return http.StatusBadRequest, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.tracker.PutUser(&user)
|
|
||||||
return http.StatusOK, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) delUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
|
||||||
s.tracker.DeleteUser(p.ByName("passkey"))
|
|
||||||
return http.StatusOK, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) getClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
func (s *Server) getClient(w http.ResponseWriter, r *http.Request, p httprouter.Params) (int, error) {
|
||||||
if err := s.tracker.ClientApproved(p.ByName("clientID")); err != nil {
|
if err := s.tracker.ClientApproved(p.ByName("clientID")); err != nil {
|
||||||
return http.StatusNotFound, err
|
return http.StatusNotFound, err
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
# Implementing a Driver
|
|
||||||
|
|
||||||
The [`backend`] package is meant to provide announce deltas to a slower and more consistent database, such as the one powering a torrent-indexing website. Implementing a backend driver is heavily inspired by the standard library's [`database/sql`] package: simply create a package that implements the [`backend.Driver`] and [`backend.Conn`] interfaces and calls [`backend.Register`] in it's [`init()`]. Please note that [`backend.Conn`] must be thread-safe. A great place to start is to read the [`no-op`] driver which comes out-of-the-box with Chihaya and is meant to be used for public trackers.
|
|
||||||
|
|
||||||
[`init()`]: http://golang.org/ref/spec#Program_execution
|
|
||||||
[`database/sql`]: http://godoc.org/database/sql
|
|
||||||
[`backend`]: http://godoc.org/github.com/chihaya/chihaya/backend
|
|
||||||
[`backend.Register`]: http://godoc.org/github.com/chihaya/chihaya/backend#Register
|
|
||||||
[`backend.Driver`]: http://godoc.org/github.com/chihaya/chihaya/backend#Driver
|
|
||||||
[`backend.Conn`]: http://godoc.org/github.com/chihaya/chihaya/backend#Conn
|
|
||||||
[`no-op`]: http://godoc.org/github.com/chihaya/chihaya/backend/noop
|
|
||||||
|
|
||||||
## Creating a binary with your own driver
|
|
||||||
|
|
||||||
Chihaya is designed to be extended. If you require more than the drivers provided out-of-the-box, you are free to create your own and then produce your own custom Chihaya binary. To create this binary, simply create your own main package, import your custom drivers, then call [`chihaya.Boot`] from main.
|
|
||||||
|
|
||||||
[`chihaya.Boot`]: http://godoc.org/github.com/chihaya/chihaya
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/chihaya/chihaya"
|
|
||||||
|
|
||||||
// Import any of your own drivers.
|
|
||||||
_ "github.com/yourusername/chihaya-custom-backend"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Start Chihaya normally.
|
|
||||||
chihaya.Boot()
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright 2015 The Chihaya Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by the BSD 2-Clause license,
|
|
||||||
// which can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package backend provides a generic interface for manipulating a
|
|
||||||
// BitTorrent tracker's consistent backend data store (usually for
|
|
||||||
// a web application).
|
|
||||||
package backend
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/chihaya/chihaya/config"
|
|
||||||
"github.com/chihaya/chihaya/tracker/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
var drivers = make(map[string]Driver)
|
|
||||||
|
|
||||||
// Driver represents an interface to a long-running connection with a
|
|
||||||
// consistent data store.
|
|
||||||
type Driver interface {
|
|
||||||
New(*config.DriverConfig) (Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register makes a database driver available by the provided name.
|
|
||||||
// If Register is called twice with the same name or if driver is nil,
|
|
||||||
// it panics.
|
|
||||||
func Register(name string, driver Driver) {
|
|
||||||
if driver == nil {
|
|
||||||
panic("backend: Register driver is nil")
|
|
||||||
}
|
|
||||||
if _, dup := drivers[name]; dup {
|
|
||||||
panic("backend: Register called twice for driver " + name)
|
|
||||||
}
|
|
||||||
drivers[name] = driver
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open creates a connection specified by a configuration.
|
|
||||||
func Open(cfg *config.DriverConfig) (Conn, error) {
|
|
||||||
driver, ok := drivers[cfg.Name]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"backend: unknown driver %q (forgotten import?)",
|
|
||||||
cfg.Name,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return driver.New(cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conn represents a connection to the data store.
|
|
||||||
type Conn interface {
|
|
||||||
// Close terminates connections to the database(s) and gracefully shuts
|
|
||||||
// down the driver
|
|
||||||
Close() error
|
|
||||||
|
|
||||||
// Ping just checks to see if the database is still alive. This is typically
|
|
||||||
// used for health checks.
|
|
||||||
Ping() error
|
|
||||||
|
|
||||||
// RecordAnnounce is called once per announce, and is passed the delta in
|
|
||||||
// statistics for the client peer since its last announce.
|
|
||||||
RecordAnnounce(delta *models.AnnounceDelta) error
|
|
||||||
|
|
||||||
// LoadTorrents fetches and returns the specified torrents.
|
|
||||||
LoadTorrents(ids []uint64) ([]*models.Torrent, error)
|
|
||||||
|
|
||||||
// LoadAllTorrents fetches and returns all torrents.
|
|
||||||
LoadAllTorrents() ([]*models.Torrent, error)
|
|
||||||
|
|
||||||
// LoadUsers fetches and returns the specified users.
|
|
||||||
LoadUsers(ids []uint64) ([]*models.User, error)
|
|
||||||
|
|
||||||
// LoadAllUsers fetches and returns all users.
|
|
||||||
LoadAllUsers() ([]*models.User, error)
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright 2015 The Chihaya Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by the BSD 2-Clause license,
|
|
||||||
// which can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package noop implements a Chihaya backend storage driver as a no-op. This is
|
|
||||||
// useful for running Chihaya as a public tracker.
|
|
||||||
package noop
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/chihaya/chihaya/backend"
|
|
||||||
"github.com/chihaya/chihaya/config"
|
|
||||||
"github.com/chihaya/chihaya/tracker/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type driver struct{}
|
|
||||||
|
|
||||||
// NoOp is a backend driver for Chihaya that does nothing. This is used by
|
|
||||||
// public trackers.
|
|
||||||
type NoOp struct{}
|
|
||||||
|
|
||||||
// New returns a new Chihaya backend driver that does nothing.
|
|
||||||
func (d *driver) New(cfg *config.DriverConfig) (backend.Conn, error) {
|
|
||||||
return &NoOp{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close returns nil.
|
|
||||||
func (n *NoOp) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping returns nil.
|
|
||||||
func (n *NoOp) Ping() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecordAnnounce returns nil.
|
|
||||||
func (n *NoOp) RecordAnnounce(delta *models.AnnounceDelta) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadTorrents returns (nil, nil).
|
|
||||||
func (n *NoOp) LoadTorrents(ids []uint64) ([]*models.Torrent, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAllTorrents returns (nil, nil).
|
|
||||||
func (n *NoOp) LoadAllTorrents() ([]*models.Torrent, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadUsers returns (nil, nil).
|
|
||||||
func (n *NoOp) LoadUsers(ids []uint64) ([]*models.User, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAllUsers returns (nil, nil).
|
|
||||||
func (n *NoOp) LoadAllUsers() ([]*models.User, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init registers the noop driver as a backend for Chihaya.
|
|
||||||
func init() {
|
|
||||||
backend.Register("noop", &driver{})
|
|
||||||
}
|
|
|
@ -23,9 +23,6 @@ import (
|
||||||
"github.com/chihaya/chihaya/stats"
|
"github.com/chihaya/chihaya/stats"
|
||||||
"github.com/chihaya/chihaya/tracker"
|
"github.com/chihaya/chihaya/tracker"
|
||||||
"github.com/chihaya/chihaya/udp"
|
"github.com/chihaya/chihaya/udp"
|
||||||
|
|
||||||
// See the README for how to import custom drivers.
|
|
||||||
_ "github.com/chihaya/chihaya/backend/noop"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -7,16 +7,11 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrMissingRequiredParam is used by drivers to indicate that an entry required
|
|
||||||
// to be within the DriverConfig.Params map is not present.
|
|
||||||
var ErrMissingRequiredParam = errors.New("A parameter that was required by a driver is not present")
|
|
||||||
|
|
||||||
// Duration wraps a time.Duration and adds JSON marshalling.
|
// Duration wraps a time.Duration and adds JSON marshalling.
|
||||||
type Duration struct{ time.Duration }
|
type Duration struct{ time.Duration }
|
||||||
|
|
||||||
|
@ -33,13 +28,6 @@ func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DriverConfig is the configuration used to connect to a tracker.Driver or
|
|
||||||
// a backend.Driver.
|
|
||||||
type DriverConfig struct {
|
|
||||||
Name string `json:"driver"`
|
|
||||||
Params map[string]string `json:"params,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubnetConfig is the configuration used to specify if local peers should be
|
// SubnetConfig is the configuration used to specify if local peers should be
|
||||||
// given a preference when responding to an announce.
|
// given a preference when responding to an announce.
|
||||||
type SubnetConfig struct {
|
type SubnetConfig struct {
|
||||||
|
@ -75,8 +63,6 @@ type WhitelistConfig struct {
|
||||||
// TrackerConfig is the configuration for tracker functionality.
|
// TrackerConfig is the configuration for tracker functionality.
|
||||||
type TrackerConfig struct {
|
type TrackerConfig struct {
|
||||||
CreateOnAnnounce bool `json:"createOnAnnounce"`
|
CreateOnAnnounce bool `json:"createOnAnnounce"`
|
||||||
PrivateEnabled bool `json:"privateEnabled"`
|
|
||||||
FreeleechEnabled bool `json:"freeleechEnabled"`
|
|
||||||
PurgeInactiveTorrents bool `json:"purgeInactiveTorrents"`
|
PurgeInactiveTorrents bool `json:"purgeInactiveTorrents"`
|
||||||
Announce Duration `json:"announce"`
|
Announce Duration `json:"announce"`
|
||||||
MinAnnounce Duration `json:"minAnnounce"`
|
MinAnnounce Duration `json:"minAnnounce"`
|
||||||
|
@ -119,7 +105,6 @@ type Config struct {
|
||||||
APIConfig
|
APIConfig
|
||||||
HTTPConfig
|
HTTPConfig
|
||||||
UDPConfig
|
UDPConfig
|
||||||
DriverConfig
|
|
||||||
StatsConfig
|
StatsConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +112,6 @@ type Config struct {
|
||||||
var DefaultConfig = Config{
|
var DefaultConfig = Config{
|
||||||
TrackerConfig: TrackerConfig{
|
TrackerConfig: TrackerConfig{
|
||||||
CreateOnAnnounce: true,
|
CreateOnAnnounce: true,
|
||||||
PrivateEnabled: false,
|
|
||||||
FreeleechEnabled: false,
|
|
||||||
PurgeInactiveTorrents: true,
|
PurgeInactiveTorrents: true,
|
||||||
Announce: Duration{30 * time.Minute},
|
Announce: Duration{30 * time.Minute},
|
||||||
MinAnnounce: Duration{15 * time.Minute},
|
MinAnnounce: Duration{15 * time.Minute},
|
||||||
|
@ -166,10 +149,6 @@ var DefaultConfig = Config{
|
||||||
ListenAddr: "localhost:6882",
|
ListenAddr: "localhost:6882",
|
||||||
},
|
},
|
||||||
|
|
||||||
DriverConfig: DriverConfig{
|
|
||||||
Name: "noop",
|
|
||||||
},
|
|
||||||
|
|
||||||
StatsConfig: StatsConfig{
|
StatsConfig: StatsConfig{
|
||||||
BufferSize: 0,
|
BufferSize: 0,
|
||||||
IncludeMem: true,
|
IncludeMem: true,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
{
|
{
|
||||||
"createOnAnnounce": true,
|
"createOnAnnounce": true,
|
||||||
"privateEnabled": false,
|
|
||||||
"freeleechEnabled": false,
|
|
||||||
"purgeInactiveTorrents": true,
|
"purgeInactiveTorrents": true,
|
||||||
"announce": "30m",
|
"announce": "30m",
|
||||||
"minAnnounce": "15m",
|
"minAnnounce": "15m",
|
||||||
|
|
|
@ -120,46 +120,6 @@ func TestStalePeerPurging(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrivateAnnounce(t *testing.T) {
|
|
||||||
cfg := config.DefaultConfig
|
|
||||||
cfg.PrivateEnabled = true
|
|
||||||
|
|
||||||
tkr, err := tracker.New(&cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPrivateTestData(tkr)
|
|
||||||
|
|
||||||
srv, err := createServer(tkr, &cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer srv.Close()
|
|
||||||
baseURL := srv.URL
|
|
||||||
|
|
||||||
peer1 := makePeerParams("-TR2820-peer1", false)
|
|
||||||
peer2 := makePeerParams("-TR2820-peer2", false)
|
|
||||||
peer3 := makePeerParams("-TR2820-peer3", true)
|
|
||||||
|
|
||||||
expected := makeResponse(0, 1, peer1)
|
|
||||||
srv.URL = baseURL + "/users/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv1"
|
|
||||||
checkAnnounce(peer1, expected, srv, t)
|
|
||||||
|
|
||||||
expected = makeResponse(0, 2, peer1)
|
|
||||||
srv.URL = baseURL + "/users/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv2"
|
|
||||||
checkAnnounce(peer2, expected, srv, t)
|
|
||||||
|
|
||||||
expected = makeResponse(1, 2, peer1, peer2)
|
|
||||||
srv.URL = baseURL + "/users/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv3"
|
|
||||||
checkAnnounce(peer3, expected, srv, t)
|
|
||||||
|
|
||||||
expected = makeResponse(1, 2, peer2, peer3)
|
|
||||||
srv.URL = baseURL + "/users/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv1"
|
|
||||||
checkAnnounce(peer1, expected, srv, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPreferredSubnet(t *testing.T) {
|
func TestPreferredSubnet(t *testing.T) {
|
||||||
cfg := config.DefaultConfig
|
cfg := config.DefaultConfig
|
||||||
cfg.PreferredSubnet = true
|
cfg.PreferredSubnet = true
|
||||||
|
@ -337,29 +297,3 @@ func checkAnnounce(p params, expected interface{}, srv *httptest.Server, t *test
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadPrivateTestData(tkr *tracker.Tracker) {
|
|
||||||
users := []string{
|
|
||||||
"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv1",
|
|
||||||
"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv2",
|
|
||||||
"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv3",
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, passkey := range users {
|
|
||||||
tkr.PutUser(&models.User{
|
|
||||||
ID: uint64(i + 1),
|
|
||||||
Passkey: passkey,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
tkr.PutClient("TR2820")
|
|
||||||
|
|
||||||
torrent := &models.Torrent{
|
|
||||||
ID: 1,
|
|
||||||
Infohash: infoHash,
|
|
||||||
Seeders: models.NewPeerMap(true, tkr.Config),
|
|
||||||
Leechers: models.NewPeerMap(false, tkr.Config),
|
|
||||||
}
|
|
||||||
|
|
||||||
tkr.PutTorrent(torrent)
|
|
||||||
}
|
|
||||||
|
|
|
@ -73,13 +73,8 @@ func makeHandler(handler ResponseHandler) httprouter.Handle {
|
||||||
func newRouter(s *Server) *httprouter.Router {
|
func newRouter(s *Server) *httprouter.Router {
|
||||||
r := httprouter.New()
|
r := httprouter.New()
|
||||||
|
|
||||||
if s.config.PrivateEnabled {
|
r.GET("/announce", makeHandler(s.serveAnnounce))
|
||||||
r.GET("/users/:passkey/announce", makeHandler(s.serveAnnounce))
|
r.GET("/scrape", makeHandler(s.serveScrape))
|
||||||
r.GET("/users/:passkey/scrape", makeHandler(s.serveScrape))
|
|
||||||
} else {
|
|
||||||
r.GET("/announce", makeHandler(s.serveAnnounce))
|
|
||||||
r.GET("/scrape", makeHandler(s.serveScrape))
|
|
||||||
}
|
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@ import (
|
||||||
"github.com/chihaya/chihaya/config"
|
"github.com/chihaya/chihaya/config"
|
||||||
"github.com/chihaya/chihaya/stats"
|
"github.com/chihaya/chihaya/stats"
|
||||||
"github.com/chihaya/chihaya/tracker"
|
"github.com/chihaya/chihaya/tracker"
|
||||||
|
|
||||||
_ "github.com/chihaya/chihaya/backend/noop"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type params map[string]string
|
type params map[string]string
|
||||||
|
|
|
@ -76,7 +76,6 @@ func (s *Server) newAnnounce(r *http.Request, p httprouter.Params) (*models.Anno
|
||||||
Infohash: infohash,
|
Infohash: infohash,
|
||||||
Left: left,
|
Left: left,
|
||||||
NumWant: numWant,
|
NumWant: numWant,
|
||||||
Passkey: p.ByName("passkey"),
|
|
||||||
PeerID: peerID,
|
PeerID: peerID,
|
||||||
Uploaded: uploaded,
|
Uploaded: uploaded,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -98,9 +97,7 @@ func (s *Server) newScrape(r *http.Request, p httprouter.Params) (*models.Scrape
|
||||||
}
|
}
|
||||||
|
|
||||||
return &models.Scrape{
|
return &models.Scrape{
|
||||||
Config: s.config,
|
Config: s.config,
|
||||||
|
|
||||||
Passkey: p.ByName("passkey"),
|
|
||||||
Infohashes: q.Infohashes,
|
Infohashes: q.Infohashes,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,6 @@ func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *models.User
|
|
||||||
if tkr.Config.PrivateEnabled {
|
|
||||||
if user, err = tkr.FindUser(ann.Passkey); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent, err := tkr.FindTorrent(ann.Infohash)
|
torrent, err := tkr.FindTorrent(ann.Infohash)
|
||||||
|
|
||||||
if err == models.ErrTorrentDNE && tkr.Config.CreateOnAnnounce {
|
if err == models.ErrTorrentDNE && tkr.Config.CreateOnAnnounce {
|
||||||
|
@ -40,30 +33,19 @@ func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ann.BuildPeer(user, torrent)
|
ann.BuildPeer(torrent)
|
||||||
var delta *models.AnnounceDelta
|
|
||||||
|
|
||||||
if tkr.Config.PrivateEnabled {
|
_, err = tkr.updateSwarm(ann)
|
||||||
delta = newAnnounceDelta(ann, torrent)
|
|
||||||
}
|
|
||||||
|
|
||||||
created, err := tkr.updateSwarm(ann)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
snatched, err := tkr.handleEvent(ann)
|
_, err = tkr.handleEvent(ann)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if tkr.Config.PrivateEnabled {
|
if tkr.Config.PurgeInactiveTorrents && torrent.PeerCount() == 0 {
|
||||||
delta.Created = created
|
|
||||||
delta.Snatched = snatched
|
|
||||||
if err = tkr.Backend.RecordAnnounce(delta); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if tkr.Config.PurgeInactiveTorrents && torrent.PeerCount() == 0 {
|
|
||||||
// Rather than deleting the torrent explicitly, let the tracker driver
|
// Rather than deleting the torrent explicitly, let the tracker driver
|
||||||
// ensure there are no race conditions.
|
// ensure there are no race conditions.
|
||||||
tkr.PurgeInactiveTorrent(torrent.Infohash)
|
tkr.PurgeInactiveTorrent(torrent.Infohash)
|
||||||
|
@ -74,49 +56,6 @@ func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) {
|
||||||
return w.WriteAnnounce(newAnnounceResponse(ann))
|
return w.WriteAnnounce(newAnnounceResponse(ann))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds a partially populated AnnounceDelta, without the Snatched and Created
|
|
||||||
// fields set.
|
|
||||||
func newAnnounceDelta(ann *models.Announce, t *models.Torrent) *models.AnnounceDelta {
|
|
||||||
var oldUp, oldDown, rawDeltaUp, rawDeltaDown uint64
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case t.Seeders.Contains(ann.Peer.Key()):
|
|
||||||
oldPeer, _ := t.Seeders.LookUp(ann.Peer.Key())
|
|
||||||
oldUp = oldPeer.Uploaded
|
|
||||||
oldDown = oldPeer.Downloaded
|
|
||||||
case t.Leechers.Contains(ann.Peer.Key()):
|
|
||||||
oldPeer, _ := t.Leechers.LookUp(ann.Peer.Key())
|
|
||||||
oldUp = oldPeer.Uploaded
|
|
||||||
oldDown = oldPeer.Downloaded
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restarting a torrent may cause a delta to be negative.
|
|
||||||
if ann.Peer.Uploaded > oldUp {
|
|
||||||
rawDeltaUp = ann.Peer.Uploaded - oldUp
|
|
||||||
}
|
|
||||||
if ann.Peer.Downloaded > oldDown {
|
|
||||||
rawDeltaDown = ann.Peer.Downloaded - oldDown
|
|
||||||
}
|
|
||||||
|
|
||||||
uploaded := uint64(float64(rawDeltaUp) * ann.User.UpMultiplier * ann.Torrent.UpMultiplier)
|
|
||||||
downloaded := uint64(float64(rawDeltaDown) * ann.User.DownMultiplier * ann.Torrent.DownMultiplier)
|
|
||||||
|
|
||||||
if ann.Config.FreeleechEnabled {
|
|
||||||
downloaded = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return &models.AnnounceDelta{
|
|
||||||
Peer: ann.Peer,
|
|
||||||
Torrent: ann.Torrent,
|
|
||||||
User: ann.User,
|
|
||||||
|
|
||||||
Uploaded: uploaded,
|
|
||||||
RawUploaded: rawDeltaUp,
|
|
||||||
Downloaded: downloaded,
|
|
||||||
RawDownloaded: rawDeltaDown,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateSwarm handles the changes to a torrent's swarm given an announce.
|
// updateSwarm handles the changes to a torrent's swarm given an announce.
|
||||||
func (tkr *Tracker) updateSwarm(ann *models.Announce) (created bool, err error) {
|
func (tkr *Tracker) updateSwarm(ann *models.Announce) (created bool, err error) {
|
||||||
var createdv4, createdv6 bool
|
var createdv4, createdv6 bool
|
||||||
|
|
|
@ -24,17 +24,11 @@ var (
|
||||||
// not a leecher or a "stopped" event while not active.
|
// not a leecher or a "stopped" event while not active.
|
||||||
ErrBadRequest = ClientError("bad request")
|
ErrBadRequest = ClientError("bad request")
|
||||||
|
|
||||||
// ErrUserDNE is returned when a user does not exist.
|
|
||||||
ErrUserDNE = NotFoundError("user does not exist")
|
|
||||||
|
|
||||||
// ErrTorrentDNE is returned when a torrent does not exist.
|
// ErrTorrentDNE is returned when a torrent does not exist.
|
||||||
ErrTorrentDNE = NotFoundError("torrent does not exist")
|
ErrTorrentDNE = NotFoundError("torrent does not exist")
|
||||||
|
|
||||||
// ErrClientUnapproved is returned when a clientID is not in the whitelist.
|
// ErrClientUnapproved is returned when a clientID is not in the whitelist.
|
||||||
ErrClientUnapproved = ClientError("client is not approved")
|
ErrClientUnapproved = ClientError("client is not approved")
|
||||||
|
|
||||||
// ErrInvalidPasskey is returned when a passkey is not properly formatted.
|
|
||||||
ErrInvalidPasskey = ClientError("passkey is invalid")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientError string
|
type ClientError string
|
||||||
|
@ -89,8 +83,6 @@ type Endpoint struct {
|
||||||
// Peer represents a participant in a BitTorrent swarm.
|
// Peer represents a participant in a BitTorrent swarm.
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
UserID uint64 `json:"userId"`
|
|
||||||
TorrentID uint64 `json:"torrentId"`
|
|
||||||
Uploaded uint64 `json:"uploaded"`
|
Uploaded uint64 `json:"uploaded"`
|
||||||
Downloaded uint64 `json:"downloaded"`
|
Downloaded uint64 `json:"downloaded"`
|
||||||
Left uint64 `json:"left"`
|
Left uint64 `json:"left"`
|
||||||
|
@ -117,16 +109,12 @@ func (p *Peer) Key() PeerKey {
|
||||||
|
|
||||||
// Torrent represents a BitTorrent swarm and its metadata.
|
// Torrent represents a BitTorrent swarm and its metadata.
|
||||||
type Torrent struct {
|
type Torrent struct {
|
||||||
ID uint64 `json:"id"`
|
Infohash string `json:"infohash"`
|
||||||
Infohash string `json:"infohash"`
|
Snatches uint64 `json:"snatches"`
|
||||||
|
LastAction int64 `json:"lastAction"`
|
||||||
|
|
||||||
Seeders *PeerMap `json:"seeders"`
|
Seeders *PeerMap `json:"seeders"`
|
||||||
Leechers *PeerMap `json:"leechers"`
|
Leechers *PeerMap `json:"leechers"`
|
||||||
|
|
||||||
Snatches uint64 `json:"snatches"`
|
|
||||||
UpMultiplier float64 `json:"upMultiplier"`
|
|
||||||
DownMultiplier float64 `json:"downMultiplier"`
|
|
||||||
LastAction int64 `json:"lastAction"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerCount returns the total number of peers connected on this Torrent.
|
// PeerCount returns the total number of peers connected on this Torrent.
|
||||||
|
@ -134,15 +122,6 @@ func (t *Torrent) PeerCount() int {
|
||||||
return t.Seeders.Len() + t.Leechers.Len()
|
return t.Seeders.Len() + t.Leechers.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
// User is a registered user for private trackers.
|
|
||||||
type User struct {
|
|
||||||
ID uint64 `json:"id"`
|
|
||||||
Passkey string `json:"passkey"`
|
|
||||||
|
|
||||||
UpMultiplier float64 `json:"upMultiplier"`
|
|
||||||
DownMultiplier float64 `json:"downMultiplier"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Announce is an Announce by a Peer.
|
// Announce is an Announce by a Peer.
|
||||||
type Announce struct {
|
type Announce struct {
|
||||||
Config *config.Config `json:"config"`
|
Config *config.Config `json:"config"`
|
||||||
|
@ -155,12 +134,10 @@ type Announce struct {
|
||||||
Infohash string `json:"infohash"`
|
Infohash string `json:"infohash"`
|
||||||
Left uint64 `json:"left"`
|
Left uint64 `json:"left"`
|
||||||
NumWant int `json:"numwant"`
|
NumWant int `json:"numwant"`
|
||||||
Passkey string `json:"passkey"`
|
|
||||||
PeerID string `json:"peer_id"`
|
PeerID string `json:"peer_id"`
|
||||||
Uploaded uint64 `json:"uploaded"`
|
Uploaded uint64 `json:"uploaded"`
|
||||||
|
|
||||||
Torrent *Torrent `json:"-"`
|
Torrent *Torrent `json:"-"`
|
||||||
User *User `json:"-"`
|
|
||||||
Peer *Peer `json:"-"`
|
Peer *Peer `json:"-"`
|
||||||
PeerV4 *Peer `json:"-"` // Only valid if HasIPv4() is true.
|
PeerV4 *Peer `json:"-"` // Only valid if HasIPv4() is true.
|
||||||
PeerV6 *Peer `json:"-"` // Only valid if HasIPv6() is true.
|
PeerV6 *Peer `json:"-"` // Only valid if HasIPv6() is true.
|
||||||
|
@ -193,11 +170,9 @@ func (a *Announce) HasIPv6() bool {
|
||||||
return a.IPv6.IP != nil
|
return a.IPv6.IP != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildPeer creates the Peer representation of an Announce. When provided nil
|
// BuildPeer creates the Peer representation of an Announce. BuildPeer creates
|
||||||
// for the user or torrent parameter, it creates a Peer{UserID: 0} or
|
// one peer for each IP in the announce, and panics if there are none.
|
||||||
// Peer{TorrentID: 0}, respectively. BuildPeer creates one peer for each IP
|
func (a *Announce) BuildPeer(t *Torrent) {
|
||||||
// in the announce, and panics if there are none.
|
|
||||||
func (a *Announce) BuildPeer(u *User, t *Torrent) {
|
|
||||||
a.Peer = &Peer{
|
a.Peer = &Peer{
|
||||||
ID: a.PeerID,
|
ID: a.PeerID,
|
||||||
Uploaded: a.Uploaded,
|
Uploaded: a.Uploaded,
|
||||||
|
@ -207,15 +182,9 @@ func (a *Announce) BuildPeer(u *User, t *Torrent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if t != nil {
|
if t != nil {
|
||||||
a.Peer.TorrentID = t.ID
|
|
||||||
a.Torrent = t
|
a.Torrent = t
|
||||||
}
|
}
|
||||||
|
|
||||||
if u != nil {
|
|
||||||
a.Peer.UserID = u.ID
|
|
||||||
a.User = u
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.HasIPv4() && a.HasIPv6() {
|
if a.HasIPv4() && a.HasIPv6() {
|
||||||
a.PeerV4 = a.Peer
|
a.PeerV4 = a.Peer
|
||||||
a.PeerV4.Endpoint = a.IPv4
|
a.PeerV4.Endpoint = a.IPv4
|
||||||
|
@ -230,31 +199,10 @@ func (a *Announce) BuildPeer(u *User, t *Torrent) {
|
||||||
} else {
|
} else {
|
||||||
panic("models: announce must have an IP")
|
panic("models: announce must have an IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnnounceDelta contains the changes to a Peer's state. These changes are
|
|
||||||
// recorded by the backend driver.
|
|
||||||
type AnnounceDelta struct {
|
|
||||||
Peer *Peer
|
|
||||||
Torrent *Torrent
|
|
||||||
User *User
|
|
||||||
|
|
||||||
// Created is true if this announce created a new peer or changed an existing
|
|
||||||
// peer's address
|
|
||||||
Created bool
|
|
||||||
// Snatched is true if this announce completed the download
|
|
||||||
Snatched bool
|
|
||||||
|
|
||||||
// Uploaded contains the upload delta for this announce, in bytes
|
|
||||||
Uploaded uint64
|
|
||||||
RawUploaded uint64
|
|
||||||
|
|
||||||
// Downloaded contains the download delta for this announce, in bytes
|
|
||||||
Downloaded uint64
|
|
||||||
RawDownloaded uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnnounceResponse contains the information needed to fulfill an announce.
|
// AnnounceResponse contains the information needed to fulfill an announce.
|
||||||
type AnnounceResponse struct {
|
type AnnounceResponse struct {
|
||||||
Announce *Announce
|
Announce *Announce
|
||||||
|
@ -267,9 +215,7 @@ type AnnounceResponse struct {
|
||||||
|
|
||||||
// Scrape is a Scrape by a Peer.
|
// Scrape is a Scrape by a Peer.
|
||||||
type Scrape struct {
|
type Scrape struct {
|
||||||
Config *config.Config `json:"config"`
|
Config *config.Config `json:"config"`
|
||||||
|
|
||||||
Passkey string
|
|
||||||
Infohashes []string
|
Infohashes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,5 +201,5 @@ func AppendPeer(ipv4s, ipv6s *PeerList, ann *Announce, peer *Peer) int {
|
||||||
|
|
||||||
// peersEquivalent checks if two peers represent the same entity.
|
// peersEquivalent checks if two peers represent the same entity.
|
||||||
func peersEquivalent(a, b *Peer) bool {
|
func peersEquivalent(a, b *Peer) bool {
|
||||||
return a.ID == b.ID || a.UserID != 0 && a.UserID == b.UserID
|
return a.ID == b.ID
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,6 @@ import (
|
||||||
// HandleScrape encapsulates all the logic of handling a BitTorrent client's
|
// HandleScrape encapsulates all the logic of handling a BitTorrent client's
|
||||||
// scrape without being coupled to any transport protocol.
|
// scrape without being coupled to any transport protocol.
|
||||||
func (tkr *Tracker) HandleScrape(scrape *models.Scrape, w Writer) (err error) {
|
func (tkr *Tracker) HandleScrape(scrape *models.Scrape, w Writer) (err error) {
|
||||||
if tkr.Config.PrivateEnabled {
|
|
||||||
if _, err = tkr.FindUser(scrape.Passkey); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var torrents []*models.Torrent
|
var torrents []*models.Torrent
|
||||||
for _, infohash := range scrape.Infohashes {
|
for _, infohash := range scrape.Infohashes {
|
||||||
torrent, err := tkr.FindTorrent(infohash)
|
torrent, err := tkr.FindTorrent(infohash)
|
||||||
|
|
|
@ -22,9 +22,6 @@ type Torrents struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
users map[string]*models.User
|
|
||||||
usersM sync.RWMutex
|
|
||||||
|
|
||||||
shards []Torrents
|
shards []Torrents
|
||||||
size int32
|
size int32
|
||||||
|
|
||||||
|
@ -34,7 +31,6 @@ type Storage struct {
|
||||||
|
|
||||||
func NewStorage(cfg *config.Config) *Storage {
|
func NewStorage(cfg *config.Config) *Storage {
|
||||||
s := &Storage{
|
s := &Storage{
|
||||||
users: make(map[string]*models.User),
|
|
||||||
shards: make([]Torrents, cfg.TorrentMapShards),
|
shards: make([]Torrents, cfg.TorrentMapShards),
|
||||||
clients: make(map[string]bool),
|
clients: make(map[string]bool),
|
||||||
}
|
}
|
||||||
|
@ -251,34 +247,6 @@ func (s *Storage) PurgeInactivePeers(purgeEmptyTorrents bool, before time.Time)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) FindUser(passkey string) (*models.User, error) {
|
|
||||||
s.usersM.RLock()
|
|
||||||
defer s.usersM.RUnlock()
|
|
||||||
|
|
||||||
user, exists := s.users[passkey]
|
|
||||||
if !exists {
|
|
||||||
return nil, models.ErrUserDNE
|
|
||||||
}
|
|
||||||
|
|
||||||
userCopy := *user
|
|
||||||
return &userCopy, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) PutUser(user *models.User) {
|
|
||||||
s.usersM.Lock()
|
|
||||||
defer s.usersM.Unlock()
|
|
||||||
|
|
||||||
userCopy := *user
|
|
||||||
s.users[user.Passkey] = &userCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) DeleteUser(passkey string) {
|
|
||||||
s.usersM.Lock()
|
|
||||||
defer s.usersM.Unlock()
|
|
||||||
|
|
||||||
delete(s.users, passkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) ClientApproved(peerID string) error {
|
func (s *Storage) ClientApproved(peerID string) error {
|
||||||
s.clientsM.RLock()
|
s.clientsM.RLock()
|
||||||
defer s.clientsM.RUnlock()
|
defer s.clientsM.RUnlock()
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/chihaya/chihaya/backend"
|
|
||||||
"github.com/chihaya/chihaya/config"
|
"github.com/chihaya/chihaya/config"
|
||||||
"github.com/chihaya/chihaya/tracker/models"
|
"github.com/chihaya/chihaya/tracker/models"
|
||||||
)
|
)
|
||||||
|
@ -19,22 +18,15 @@ import (
|
||||||
// Tracker represents the logic necessary to service BitTorrent announces,
|
// Tracker represents the logic necessary to service BitTorrent announces,
|
||||||
// independently of the underlying data transports used.
|
// independently of the underlying data transports used.
|
||||||
type Tracker struct {
|
type Tracker struct {
|
||||||
Config *config.Config
|
Config *config.Config
|
||||||
Backend backend.Conn
|
|
||||||
*Storage
|
*Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Tracker, and opens any necessary connections.
|
// New creates a new Tracker, and opens any necessary connections.
|
||||||
// Maintenance routines are automatically spawned in the background.
|
// Maintenance routines are automatically spawned in the background.
|
||||||
func New(cfg *config.Config) (*Tracker, error) {
|
func New(cfg *config.Config) (*Tracker, error) {
|
||||||
bc, err := backend.Open(&cfg.DriverConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tkr := &Tracker{
|
tkr := &Tracker{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Backend: bc,
|
|
||||||
Storage: NewStorage(cfg),
|
Storage: NewStorage(cfg),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +45,10 @@ func New(cfg *config.Config) (*Tracker, error) {
|
||||||
|
|
||||||
// Close gracefully shutdowns a Tracker by closing any database connections.
|
// Close gracefully shutdowns a Tracker by closing any database connections.
|
||||||
func (tkr *Tracker) Close() error {
|
func (tkr *Tracker) Close() error {
|
||||||
return tkr.Backend.Close()
|
|
||||||
|
// TODO(jzelinskie): shutdown purgeInactivePeers goroutine.
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadApprovedClients loads a list of client IDs into the tracker's storage.
|
// LoadApprovedClients loads a list of client IDs into the tracker's storage.
|
||||||
|
|
|
@ -14,8 +14,6 @@ import (
|
||||||
|
|
||||||
"github.com/chihaya/chihaya/config"
|
"github.com/chihaya/chihaya/config"
|
||||||
"github.com/chihaya/chihaya/tracker"
|
"github.com/chihaya/chihaya/tracker"
|
||||||
|
|
||||||
_ "github.com/chihaya/chihaya/backend/noop"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in a new issue