diff --git a/server/announce.go b/server/announce.go index 7dac391..a559f1b 100644 --- a/server/announce.go +++ b/server/announce.go @@ -15,7 +15,7 @@ import ( "github.com/pushrax/chihaya/storage" ) -func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { +func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { // Parse the required parameters off of a query compact, numWant, infohash, peerID, event, ip, port, uploaded, downloaded, left, err := s.validateAnnounceQuery(r) if err != nil { @@ -116,7 +116,7 @@ func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { default: // Check the user's slots to see if they're allowed to leech if s.conf.Slots && user.Slots != -1 && left != 0 { - if user.UsedSlots >= user.Slots { + if user.SlotsUsed >= user.Slots { fail(errors.New("You've run out of download slots."), w, r) return } @@ -192,7 +192,7 @@ func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { // TODO compact, response, etc... } -func (s *Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) { +func (s Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) { pq, err := parseQuery(r.URL.RawQuery) if err != nil { return false, 0, "", "", "", "", 0, 0, 0, 0, err diff --git a/storage/data.go b/storage/data.go index 379c4e2..159b88c 100644 --- a/storage/data.go +++ b/storage/data.go @@ -5,42 +5,34 @@ package storage type Peer struct { - ID string - UserID uint64 - TorrentID uint64 - - IP string - Port uint64 - - Uploaded uint64 - Downloaded uint64 - Left uint64 - - LastAnnounce int64 + ID string `json:"id"` + UserID uint64 `json:"user_id"` + TorrentID uint64 `json:"torrent_id"` + IP string `json:"ip"` + Port uint64 `json:"port"` + Uploaded uint64 `json:"uploaded"` + Downloaded uint64 `json:"downloaded` + Left uint64 `json:"left"` + LastAnnounce int64 `json:"last_announce"` } type Torrent struct { - ID uint64 - Infohash string - UpMultiplier float64 - DownMultiplier float64 - - Seeders map[string]Peer - Leechers map[string]Peer - - Snatches uint - Pruned bool - LastAction int64 + ID uint64 `json:"id"` + Infohash string `json:"infohash"` + Pruned bool `json:"pruned"` + Seeders map[string]Peer `json:"seeders"` + Leechers map[string]Peer `json:"leechers"` + Snatches uint `json:"snatches"` + UpMultiplier float64 `json:"up_multiplier"` + DownMultiplier float64 `json:"down_multipler"` + LastAction int64 `json:"last_action"` } type User struct { - ID uint64 - Passkey string - - UpMultiplier float64 - DownMultiplier float64 - - Slots int64 - UsedSlots int64 - SlotsLastChecked int64 + ID uint64 `json:"id"` + Passkey string `json:"passkey"` + UpMultiplier float64 `json:"up_multiplier"` + DownMultiplier float64 `json:"down_multiplier"` + Slots int64 `json:"slots"` + SlotsUsed int64 `json:"slots_used"` } diff --git a/storage/redis/redis.go b/storage/redis/redis.go index 35075df..fa62c30 100644 --- a/storage/redis/redis.go +++ b/storage/redis/redis.go @@ -3,9 +3,16 @@ // which can be found in the LICENSE file. // Package redis implements the storage interface for a BitTorrent tracker. + +// The client whitelist is represented as a set with the key name "whitelist" +// with an optional prefix. Torrents and users are JSON-formatted strings. +// Torrents' keys are named "torrent_" with an optional prefix. +// Users' keys are named "user_" with an optional prefix. package redis import ( + "encoding/json" + "strings" "time" "github.com/garyburd/redigo/redis" @@ -67,19 +74,17 @@ func (ds *DS) FindUser(passkey string) (*storage.User, bool, error) { conn := ds.Get() defer conn.Close() - key := ds.conf.Prefix + "User:" + passkey - reply, err := redis.Values(conn.Do("HGETALL", key)) + key := ds.conf.Prefix + "user_" + passkey + reply, err := redis.String(conn.Do("GET", key)) if err != nil { - return nil, true, err - } - - // If we get nothing back, the user isn't found. - if len(reply) == 0 { - return nil, false, nil + if err == redis.ErrNil { + return nil, false, nil + } + return nil, false, err } user := &storage.User{} - err = redis.ScanStruct(reply, user) + err = json.NewDecoder(strings.NewReader(reply)).Decode(user) if err != nil { return nil, true, err } @@ -90,19 +95,17 @@ func (ds *DS) FindTorrent(infohash string) (*storage.Torrent, bool, error) { conn := ds.Get() defer conn.Close() - key := ds.conf.Prefix + "Torrent:" + infohash - reply, err := redis.Values(conn.Do("HGETALL", key)) + key := ds.conf.Prefix + "torrent_" + infohash + reply, err := redis.String(conn.Do("GET", key)) if err != nil { + if err == redis.ErrNil { + return nil, false, nil + } return nil, false, err } - // If we get nothing back, the torrent isn't found. - if len(reply) == 0 { - return nil, false, nil - } - torrent := &storage.Torrent{} - err = redis.ScanStruct(reply, torrent) + err = json.NewDecoder(strings.NewReader(reply)).Decode(torrent) if err != nil { return nil, true, err } @@ -113,8 +116,8 @@ func (ds *DS) ClientWhitelisted(peerID string) (bool, error) { conn := ds.Get() defer conn.Close() - key := ds.conf.Prefix + "Whitelist:" + peerID - exists, err := redis.Bool(conn.Do("EXISTS", key)) + key := ds.conf.Prefix + "whitelist" + exists, err := redis.Bool(conn.Do("SISMEMBER", key, peerID)) if err != nil { return false, err }