func (tkr *Tracker) handlePeerEvent(ann *models.Announce, p *models.Peer) (snatched bool, err error) { p, t := ann.Peer, ann.Torrent switch { case ann.Event == "stopped" || ann.Event == "paused": // updateSwarm checks if the peer is active on the torrent, // so one of these branches must be followed. if t.Seeders.Contains(p.Key()) { err = tkr.DeleteSeeder(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.DeletedSeed, p.HasIPv6()) } else if t.Leechers.Contains(p.Key()) { err = tkr.DeleteLeecher(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.DeletedLeech, p.HasIPv6()) } case ann.Event == "completed": tkr.leecherFinished(t, p) snatched = true case t.Leechers.Contains(p.Key()) && ann.Left == 0: // A leecher completed but the event was never received. err = tkr.leecherFinished(t, p) } return }
// leecherFinished moves a peer from the leeching pool to the seeder pool. func (tkr *Tracker) leecherFinished(t *models.Torrent, p *models.Peer) error { if err := tkr.DeleteLeecher(t.Infohash, p); err != nil { return err } if err := tkr.PutSeeder(t.Infohash, p); err != nil { return err } stats.RecordPeerEvent(stats.Completed, p.HasIPv6()) return nil }
func (s *Storage) DeleteSeeder(infohash string, p *models.Peer) error { shard := s.getTorrentShard(infohash, false) defer shard.Unlock() torrent, exists := shard.torrents[infohash] if !exists { return models.ErrTorrentDNE } torrent.Seeders.Delete(p.Key()) return nil }
func (tkr *Tracker) handlePeerEvent(ann *models.Announce, p *models.Peer) (snatched bool, err error) { p, t := ann.Peer, ann.Torrent switch { case ann.Event == "stopped" || ann.Event == "paused": // updateSwarm checks if the peer is active on the torrent, // so one of these branches must be followed. if t.Seeders.Contains(p.Key()) { err = tkr.DeleteSeeder(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.DeletedSeed, p.HasIPv6()) } else if t.Leechers.Contains(p.Key()) { err = tkr.DeleteLeecher(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.DeletedLeech, p.HasIPv6()) } case t.Leechers.Contains(p.Key()) && (ann.Event == "completed" || ann.Left == 0): // A leecher has completed or this is the first time we've seen them since // they've completed. err = tkr.leecherFinished(t, p) if err != nil { return } // Only mark as snatched if we receive the completed event. if ann.Event == "completed" { snatched = true } } return }