diff --git a/server/scrape.go b/server/scrape.go index 6d0777f..0efd8a5 100644 --- a/server/scrape.go +++ b/server/scrape.go @@ -5,76 +5,72 @@ package server import ( - "errors" - "io" - "log" - "net/http" - "path" + "errors" + "io" + "log" + "net/http" + "path" - "github.com/pushrax/chihaya/storage" + "github.com/pushrax/chihaya/storage" ) 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) - return - } + // Parse the query + pq, err := parseQuery(r.URL.RawQuery) + if err != nil { + fail(errors.New("Error parsing query"), w, r) + return + } - // Start a transaction - tx, err := s.dbConnPool.Get() - if err != nil { - log.Fatal(err) - } + // Start a transaction + tx, err := s.dbConnPool.Get() + if err != nil { + log.Fatal(err) + } - // Find and validate the user - passkey, _ := path.Split(r.URL.Path) - _, err = validateUser(tx, passkey) - if err != nil { - fail(err, w, r) - return - } + // Find and validate the user + passkey, _ := path.Split(r.URL.Path) + _, err = validateUser(tx, passkey) + if err != nil { + fail(err, w, r) + return + } - io.WriteString(w, "d") - writeBencoded(w, "files") - if pq.Infohashes != nil { - for _, infohash := range pq.Infohashes { - torrent, exists, err := tx.FindTorrent(infohash) - if err != nil { - log.Panicf("server: %s", err) - } - if exists { - writeBencoded(w, infohash) - writeScrapeInfo(w, torrent) - } - } - } else if infohash, exists := pq.Params["info_hash"]; exists { - torrent, exists, err := tx.FindTorrent(infohash) - if err != nil { - log.Panicf("server: %s", err) - } - if exists { - writeBencoded(w, infohash) - writeScrapeInfo(w, torrent) - } - } - io.WriteString(w, "e") + io.WriteString(w, "d") + writeBencoded(w, "files") + if pq.Infohashes != nil { + for _, infohash := range pq.Infohashes { + torrent, exists, err := tx.FindTorrent(infohash) + if err != nil { + log.Panicf("server: %s", err) + } + if exists { + writeBencoded(w, infohash) + writeScrapeInfo(w, torrent) + } + } + } else if infohash, exists := pq.Params["info_hash"]; exists { + torrent, exists, err := tx.FindTorrent(infohash) + if err != nil { + log.Panicf("server: %s", err) + } + if exists { + writeBencoded(w, infohash) + writeScrapeInfo(w, torrent) + } + } + io.WriteString(w, "e") - // Finish up and write headers - r.Close = true - w.Header().Add("Content-Type", "text/plain") - w.Header().Add("Connection", "close") - w.(http.Flusher).Flush() + w.(http.Flusher).Flush() } func writeScrapeInfo(w io.Writer, torrent *storage.Torrent) { - io.WriteString(w, "d") - writeBencoded(w, "complete") - writeBencoded(w, len(torrent.Seeders)) - writeBencoded(w, "downloaded") - writeBencoded(w, torrent.Snatches) - writeBencoded(w, "incomplete") - writeBencoded(w, len(torrent.Leechers)) - io.WriteString(w, "e") + io.WriteString(w, "d") + writeBencoded(w, "complete") + writeBencoded(w, len(torrent.Seeders)) + writeBencoded(w, "downloaded") + writeBencoded(w, torrent.Snatches) + writeBencoded(w, "incomplete") + writeBencoded(w, len(torrent.Leechers)) + io.WriteString(w, "e") } diff --git a/server/server.go b/server/server.go index 5683cc9..e54c3ae 100644 --- a/server/server.go +++ b/server/server.go @@ -6,142 +6,140 @@ package server import ( - "errors" - "io" - "log" - "net" - "net/http" - "path" - "strconv" - "sync/atomic" - "time" + "errors" + "io" + "log" + "net" + "net/http" + "path" + "strconv" + "sync/atomic" + "time" - "github.com/etix/stoppableListener" + "github.com/etix/stoppableListener" - "github.com/pushrax/chihaya/config" - "github.com/pushrax/chihaya/storage" - "github.com/pushrax/chihaya/storage/tracker" + "github.com/pushrax/chihaya/config" + "github.com/pushrax/chihaya/storage" + "github.com/pushrax/chihaya/storage/tracker" ) type Server struct { - conf *config.Config - listener *stoppableListener.StoppableListener - dbConnPool tracker.Pool + conf *config.Config + listener *stoppableListener.StoppableListener + dbConnPool tracker.Pool - startTime time.Time + startTime time.Time - deltaRequests int64 - rpm int64 + deltaRequests int64 + rpm int64 - http.Server + http.Server } func New(conf *config.Config) (*Server, error) { - pool, err := tracker.Open(&conf.Cache) - if err != nil { - return nil, err - } + pool, err := tracker.Open(&conf.Cache) + if err != nil { + return nil, err + } - s := &Server{ - conf: conf, - dbConnPool: pool, - Server: http.Server{ - Addr: conf.Addr, - ReadTimeout: conf.ReadTimeout.Duration, - }, - } - s.Server.Handler = s + s := &Server{ + conf: conf, + dbConnPool: pool, + Server: http.Server{ + Addr: conf.Addr, + ReadTimeout: conf.ReadTimeout.Duration, + }, + } + s.Server.Handler = s - return s, nil + return s, nil } func (s *Server) ListenAndServe() error { - l, err := net.Listen("tcp", s.Addr) - if err != nil { - return err - } - sl := stoppableListener.Handle(l) - s.listener = sl - s.startTime = time.Now() + l, err := net.Listen("tcp", s.Addr) + if err != nil { + return err + } + sl := stoppableListener.Handle(l) + s.listener = sl + s.startTime = time.Now() - go s.updateStats() - s.Serve(s.listener) + go s.updateStats() + s.Serve(s.listener) - return nil + return nil } func (s *Server) Stop() error { - s.listener.Stop <- true - err := s.dbConnPool.Close() - if err != nil { - return err - } - return s.listener.Close() + s.listener.Stop <- true + err := s.dbConnPool.Close() + if err != nil { + return err + } + return s.listener.Close() } func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { - defer atomic.AddInt64(&s.deltaRequests, 1) + defer atomic.AddInt64(&s.deltaRequests, 1) + r.Close = true - switch r.URL.Path { - case "/stats": - s.serveStats(w, r) - return - case "/add": - s.serveAdd(w, r) - return - case "/remove": - s.serveRemove(w, r) - return - } + switch r.URL.Path { + case "/stats": + s.serveStats(w, r) + return + case "/add": + s.serveAdd(w, r) + return + case "/remove": + s.serveRemove(w, r) + return + } - _, action := path.Split(r.URL.Path) - switch action { - case "announce": - s.serveAnnounce(w, r) - return - case "scrape": - s.serveScrape(w, r) - return - default: - fail(errors.New("Unknown action"), w, r) - return - } + _, action := path.Split(r.URL.Path) + switch action { + case "announce": + s.serveAnnounce(w, r) + return + case "scrape": + s.serveScrape(w, r) + return + default: + fail(errors.New("Unknown action"), w, r) + return + } } func fail(err error, w http.ResponseWriter, r *http.Request) { - errmsg := err.Error() - message := "d14:failure reason" + strconv.Itoa(len(errmsg)) + ":" + errmsg + "e" - length, _ := io.WriteString(w, message) - r.Close = true - w.Header().Add("Content-Type", "text/plain") - w.Header().Add("Content-Length", string(length)) - w.Header().Add("Connection", "close") - w.(http.Flusher).Flush() + errmsg := err.Error() + message := "d14:failure reason" + strconv.Itoa(len(errmsg)) + ":" + errmsg + "e" + length, _ := io.WriteString(w, message) + w.Header().Add("Content-Length", string(length)) + w.(http.Flusher).Flush() } func validateUser(tx tracker.Conn, dir string) (*storage.User, error) { - if len(dir) != 34 { - return nil, errors.New("Passkey is invalid") - } - passkey := dir[1:33] + if len(dir) != 34 { + return nil, errors.New("Passkey is invalid") + } + passkey := dir[1:33] - user, exists, err := tx.FindUser(passkey) - if err != nil { - log.Panicf("server: %s", err) - } - if !exists { - return nil, errors.New("User not found") - } + user, exists, err := tx.FindUser(passkey) + if err != nil { + log.Panicf("server: %s", err) + } + if !exists { + return nil, errors.New("User not found") + } - return user, nil + return user, nil } // Takes a peer_id and returns a ClientID func parsePeerID(peerID string) (clientID string) { - if peerID[0] == '-' { - clientID = peerID[1:7] - } else { - clientID = peerID[0:6] - } - return + if peerID[0] == '-' { + clientID = peerID[1:7] + } else { + clientID = peerID[0:6] + } + return } diff --git a/server/stats.go b/server/stats.go index 19d577d..df94099 100644 --- a/server/stats.go +++ b/server/stats.go @@ -20,7 +20,6 @@ type stats struct { func (s *Server) serveStats(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - w.Header().Set("Connection", "close") stats, _ := json.Marshal(&stats{ config.Duration{time.Now().Sub(s.startTime)},