// handleEvent checks to see whether an announce has an event and if it does, // properly handles that event. func (tkr *Tracker) handleEvent(ann *models.Announce) (snatched bool, err error) { var snatchedv4, snatchedv6 bool if ann.HasIPv4() { snatchedv4, err = tkr.handlePeerEvent(ann, ann.PeerV4) if err != nil { return } } if ann.HasIPv6() { snatchedv6, err = tkr.handlePeerEvent(ann, ann.PeerV6) if err != nil { return } } if snatchedv4 || snatchedv6 { err = tkr.IncrementTorrentSnatches(ann.Torrent.Infohash) if err != nil { return } ann.Torrent.Snatches++ return true, nil } return false, nil }
// HandleAnnounce encapsulates all of the logic of handling a BitTorrent // client's Announce without being coupled to any transport protocol. func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) { if tkr.Config.ClientWhitelistEnabled { if err = tkr.ClientApproved(ann.ClientID()); err != nil { return err } } if tkr.Config.JWKSetURI != "" { err := tkr.validateJWT(ann.JWT, ann.Infohash) if err != nil { return err } } torrent, err := tkr.FindTorrent(ann.Infohash) if err == models.ErrTorrentDNE && tkr.Config.CreateOnAnnounce { torrent = &models.Torrent{ Infohash: ann.Infohash, Seeders: models.NewPeerMap(true, tkr.Config), Leechers: models.NewPeerMap(false, tkr.Config), } tkr.PutTorrent(torrent) stats.RecordEvent(stats.NewTorrent) } else if err != nil { return err } ann.BuildPeer(torrent) _, err = tkr.updateSwarm(ann) if err != nil { return err } _, err = tkr.handleEvent(ann) if err != nil { return err } if tkr.Config.PurgeInactiveTorrents && torrent.PeerCount() == 0 { // Rather than deleting the torrent explicitly, let the tracker driver // ensure there are no race conditions. tkr.PurgeInactiveTorrent(torrent.Infohash) stats.RecordEvent(stats.DeletedTorrent) } stats.RecordEvent(stats.Announce) return w.WriteAnnounce(newAnnounceResponse(ann)) }
// updateSwarm handles the changes to a torrent's swarm given an announce. func (tkr *Tracker) updateSwarm(ann *models.Announce) (created bool, err error) { var createdv4, createdv6 bool tkr.TouchTorrent(ann.Torrent.Infohash) if ann.HasIPv4() { createdv4, err = tkr.updatePeer(ann, ann.PeerV4) if err != nil { return } } if ann.HasIPv6() { createdv6, err = tkr.updatePeer(ann, ann.PeerV6) if err != nil { return } } return createdv4 || createdv6, nil }
// HandleAnnounce encapsulates all of the logic of handling a BitTorrent // client's Announce without being coupled to any transport protocol. func (tkr *Tracker) HandleAnnounce(ann *models.Announce, w Writer) (err error) { if tkr.Config.ClientWhitelistEnabled { if err = tkr.ClientApproved(ann.ClientID()); err != nil { return err } } 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) if err == models.ErrTorrentDNE && tkr.Config.CreateOnAnnounce { torrent = &models.Torrent{ Infohash: ann.Infohash, Seeders: models.NewPeerMap(true, tkr.Config), Leechers: models.NewPeerMap(false, tkr.Config), } tkr.PutTorrent(torrent) stats.RecordEvent(stats.NewTorrent) } else if err != nil { return err } ann.BuildPeer(user, torrent) var delta *models.AnnounceDelta if tkr.Config.PrivateEnabled { delta = newAnnounceDelta(ann, torrent) } created, err := tkr.updateSwarm(ann) if err != nil { return err } snatched, err := tkr.handleEvent(ann) if err != nil { return err } if tkr.Config.PrivateEnabled { 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 // ensure there are no race conditions. tkr.PurgeInactiveTorrent(torrent.Infohash) stats.RecordEvent(stats.DeletedTorrent) } stats.RecordEvent(stats.Announce) return w.WriteAnnounce(newAnnounceResponse(ann)) }