first pass with linter
This commit is contained in:
parent
f0bed27b6d
commit
b32eaebcd6
9 changed files with 80 additions and 25 deletions
|
@ -12,14 +12,17 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Duration wraps a time.Duration and adds JSON marshalling.
|
||||
type Duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
// MarshalJSON transforms a duration into JSON.
|
||||
func (d *Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON transform JSON into a Duration.
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
var str string
|
||||
err := json.Unmarshal(b, &str)
|
||||
|
@ -61,8 +64,7 @@ type Config struct {
|
|||
// Open is a shortcut to open a file, read it, and generate a Config.
|
||||
// It supports relative and absolute paths.
|
||||
func Open(path string) (*Config, error) {
|
||||
expandedPath := os.ExpandEnv(path)
|
||||
f, err := os.Open(expandedPath)
|
||||
f, err := os.Open(os.ExpandEnv(path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
|||
log.Panicf("server: %s", err)
|
||||
}
|
||||
if !whitelisted {
|
||||
fail(errors.New("Your client is not approved"), w, r)
|
||||
fail(errors.New("client is not approved"), w, r)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
|||
log.Panicf("server: %s", err)
|
||||
}
|
||||
if !exists {
|
||||
fail(errors.New("This torrent does not exist"), w, r)
|
||||
fail(errors.New("torrent does not exist"), w, r)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ func (s Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant in
|
|||
uploadedErr != nil ||
|
||||
downloadedErr != nil ||
|
||||
leftErr != nil {
|
||||
return false, 0, "", "", "", "", 0, 0, 0, 0, errors.New("Malformed request")
|
||||
return false, 0, "", "", "", "", 0, 0, 0, 0, errors.New("malformed request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ func requestedIP(r *http.Request, pq *parsedQuery) (string, error) {
|
|||
if portIndex != -1 {
|
||||
return r.RemoteAddr[0:portIndex], nil
|
||||
}
|
||||
return "", errors.New("Failed to parse IP address")
|
||||
return "", errors.New("failed to parse IP address")
|
||||
}
|
||||
|
||||
func minInt(a, b int) int {
|
||||
|
|
|
@ -8,18 +8,18 @@ import (
|
|||
var (
|
||||
baseAddr = "https://www.subdomain.tracker.com:80/"
|
||||
testInfoHash = "01234567890123456789"
|
||||
testPeerId = "-TEST01-6wfG2wk6wWLc"
|
||||
testPeerID = "-TEST01-6wfG2wk6wWLc"
|
||||
|
||||
ValidAnnounceArguments = []url.Values{
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "numwant": {"28"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "event": {"stopped"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "event": {"started"}, "numwant": {"13"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "no_peer_id": {"1"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}, "key": {"peerKey"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerId}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}, "key": {"peerKey"}, "trackerid": {"trackerId"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "numwant": {"28"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "event": {"stopped"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "ip": {"192.168.0.1"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "event": {"started"}, "numwant": {"13"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "no_peer_id": {"1"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}, "key": {"peerKey"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {testPeerID}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}, "key": {"peerKey"}, "trackerid": {"trackerId"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {"%3Ckey%3A+0x90%3E"}, "port": {"6881"}, "downloaded": {"1234"}, "left": {"4321"}, "compact": {"0"}, "no_peer_id": {"1"}, "key": {"peerKey"}, "trackerid": {"trackerId"}},
|
||||
url.Values{"info_hash": {testInfoHash}, "peer_id": {"%3Ckey%3A+0x90%3E"}, "compact": {"1"}},
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func (s *Server) serveScrape(w http.ResponseWriter, r *http.Request) {
|
|||
// Parse the query
|
||||
pq, err := parseQuery(r.URL.RawQuery)
|
||||
if err != nil {
|
||||
fail(errors.New("Error parsing query"), w, r)
|
||||
fail(errors.New("error parsing query"), w, r)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/chihaya/chihaya/storage/tracker"
|
||||
)
|
||||
|
||||
// Server represents BitTorrent tracker server.
|
||||
type Server struct {
|
||||
conf *config.Config
|
||||
listener *stoppableListener.StoppableListener
|
||||
|
@ -38,6 +39,7 @@ type Server struct {
|
|||
http.Server
|
||||
}
|
||||
|
||||
// New creates a new Server.
|
||||
func New(conf *config.Config) (*Server, error) {
|
||||
trackerPool, err := tracker.Open(&conf.Tracker)
|
||||
if err != nil {
|
||||
|
@ -66,6 +68,7 @@ func New(conf *config.Config) (*Server, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
// ListenAndServe starts listening and handling incoming HTTP requests.
|
||||
func (s *Server) ListenAndServe() error {
|
||||
l, err := net.Listen("tcp", s.Addr)
|
||||
if err != nil {
|
||||
|
@ -81,6 +84,7 @@ func (s *Server) ListenAndServe() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Stop cleanly ends the handling of incoming HTTP requests.
|
||||
func (s *Server) Stop() error {
|
||||
s.listener.Stop <- true
|
||||
err := s.trackerPool.Close()
|
||||
|
@ -106,7 +110,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
s.serveStats(w, r)
|
||||
return
|
||||
default:
|
||||
fail(errors.New("Unknown action"), w, r)
|
||||
fail(errors.New("unknown action"), w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +125,7 @@ func fail(err error, w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func validateUser(conn tracker.Conn, dir string) (*storage.User, error) {
|
||||
if len(dir) != 34 {
|
||||
return nil, errors.New("Passkey is invalid")
|
||||
return nil, errors.New("passkey is invalid")
|
||||
}
|
||||
passkey := dir[1:33]
|
||||
|
||||
|
@ -130,7 +134,7 @@ func validateUser(conn tracker.Conn, dir string) (*storage.User, error) {
|
|||
log.Panicf("server: %s", err)
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.New("User not found")
|
||||
return nil, errors.New("user not found")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
)
|
||||
|
||||
type PeerClientPair struct {
|
||||
peerId string
|
||||
clientId string
|
||||
peerID string
|
||||
clientID string
|
||||
}
|
||||
|
||||
var TestClients = []PeerClientPair{
|
||||
|
@ -59,8 +59,8 @@ var TestClients = []PeerClientPair{
|
|||
|
||||
func TestParseClientID(t *testing.T) {
|
||||
for _, pair := range TestClients {
|
||||
if parsedId := parsePeerID(pair.peerId); parsedId != pair.clientId {
|
||||
t.Error("Incorrectly parsed peer ID", pair.peerId, "as", parsedId)
|
||||
if parsedID := parsePeerID(pair.peerID); parsedID != pair.clientID {
|
||||
t.Error("Incorrectly parsed peer ID", pair.peerID, "as", parsedID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import (
|
|||
|
||||
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.DataStore) Conn
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ type Conn struct {
|
|||
func (c *Conn) FindUser(passkey string) (*storage.User, bool, error) {
|
||||
c.usersM.RLock()
|
||||
defer c.usersM.RUnlock()
|
||||
|
||||
user, ok := c.users[passkey]
|
||||
if !ok {
|
||||
return nil, false, nil
|
||||
|
@ -27,6 +28,7 @@ func (c *Conn) FindUser(passkey string) (*storage.User, bool, error) {
|
|||
func (c *Conn) FindTorrent(infohash string) (*storage.Torrent, bool, error) {
|
||||
c.torrentsM.RLock()
|
||||
defer c.torrentsM.RUnlock()
|
||||
|
||||
torrent, ok := c.torrents[infohash]
|
||||
if !ok {
|
||||
return nil, false, nil
|
||||
|
@ -38,6 +40,7 @@ func (c *Conn) FindTorrent(infohash string) (*storage.Torrent, bool, error) {
|
|||
func (c *Conn) ClientWhitelisted(peerID string) (bool, error) {
|
||||
c.whitelistM.RLock()
|
||||
defer c.whitelistM.RUnlock()
|
||||
|
||||
_, ok := c.whitelist[peerID]
|
||||
if !ok {
|
||||
return false, nil
|
||||
|
@ -48,108 +51,134 @@ func (c *Conn) ClientWhitelisted(peerID string) (bool, error) {
|
|||
func (c *Conn) RecordSnatch(u *storage.User, t *storage.Torrent) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
torrent.Snatches++
|
||||
t.Snatches++
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) MarkActive(t *storage.Torrent) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Active = true
|
||||
t.Active = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) MarkInactive(t *storage.Torrent) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Active = false
|
||||
t.Active = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) AddLeecher(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Leechers[storage.PeerMapKey(p)] = *p
|
||||
t.Leechers[storage.PeerMapKey(p)] = *p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) AddSeeder(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Leechers[storage.PeerMapKey(p)] = *p
|
||||
t.Leechers[storage.PeerMapKey(p)] = *p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) RemoveLeecher(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
delete(torrent.Leechers, storage.PeerMapKey(p))
|
||||
delete(t.Leechers, storage.PeerMapKey(p))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) RemoveSeeder(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
delete(torrent.Seeders, storage.PeerMapKey(p))
|
||||
delete(t.Seeders, storage.PeerMapKey(p))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) SetLeecher(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Leechers[storage.PeerMapKey(p)] = *p
|
||||
t.Leechers[storage.PeerMapKey(p)] = *p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) SetSeeder(t *storage.Torrent, p *storage.Peer) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent, ok := c.torrents[t.Infohash]
|
||||
if !ok {
|
||||
return tracker.ErrMissingResource
|
||||
}
|
||||
|
||||
torrent.Seeders[storage.PeerMapKey(p)] = *p
|
||||
t.Seeders[storage.PeerMapKey(p)] = *p
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -164,51 +193,65 @@ func (c *Conn) LeecherFinished(t *storage.Torrent, p *storage.Peer) error {
|
|||
|
||||
torrent.Seeders[storage.PeerMapKey(p)] = *p
|
||||
delete(torrent.Leechers, storage.PeerMapKey(p))
|
||||
|
||||
t.Seeders[storage.PeerMapKey(p)] = *p
|
||||
delete(t.Leechers, storage.PeerMapKey(p))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) AddTorrent(t *storage.Torrent) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
torrent := *t
|
||||
c.torrents[t.Infohash] = &torrent
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) RemoveTorrent(t *storage.Torrent) error {
|
||||
c.torrentsM.Lock()
|
||||
defer c.torrentsM.Unlock()
|
||||
|
||||
delete(c.torrents, t.Infohash)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) AddUser(u *storage.User) error {
|
||||
c.usersM.Lock()
|
||||
defer c.usersM.Unlock()
|
||||
|
||||
user := *u
|
||||
c.users[u.Passkey] = &user
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) RemoveUser(u *storage.User) error {
|
||||
c.usersM.Lock()
|
||||
defer c.usersM.Unlock()
|
||||
|
||||
delete(c.users, u.Passkey)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) WhitelistClient(peerID string) error {
|
||||
c.whitelistM.Lock()
|
||||
defer c.whitelistM.Unlock()
|
||||
|
||||
c.whitelist[peerID] = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) UnWhitelistClient(peerID string) error {
|
||||
c.whitelistM.Lock()
|
||||
defer c.whitelistM.Unlock()
|
||||
|
||||
delete(c.whitelist, peerID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -15,10 +15,14 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// ErrMissingResource is an error returned when a resource does not exist.
|
||||
ErrMissingResource = errors.New("tracker: resource missing")
|
||||
drivers = make(map[string]Driver)
|
||||
|
||||
drivers = make(map[string]Driver)
|
||||
)
|
||||
|
||||
// Driver represents an interface to pool of connections to storage used for
|
||||
// the tracker.
|
||||
type Driver interface {
|
||||
New(*config.DataStore) Pool
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue