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 }
func (tkr *Tracker) updatePeer(ann *models.Announce, peer *models.Peer) (created bool, err error) { p, t := ann.Peer, ann.Torrent switch { case t.Seeders.Contains(p.Key()): err = tkr.PutSeeder(t.Infohash, p) if err != nil { return } case t.Leechers.Contains(p.Key()): err = tkr.PutLeecher(t.Infohash, p) if err != nil { return } default: if ann.Left == 0 { err = tkr.PutSeeder(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.NewSeed, p.HasIPv6()) } else { err = tkr.PutLeecher(t.Infohash, p) if err != nil { return } stats.RecordPeerEvent(stats.NewLeech, p.HasIPv6()) } created = true } return }
// Purge iterates over all of the peers within a PeerMap and deletes them if // they are older than the provided time. func (pm *PeerMap) Purge(unixtime int64) { pm.Lock() defer pm.Unlock() for _, subnetmap := range pm.Peers { for key, peer := range subnetmap { if peer.LastAnnounce <= unixtime { atomic.AddInt32(&(pm.Size), -1) delete(subnetmap, key) if pm.Seeders { stats.RecordPeerEvent(stats.ReapedSeed, peer.HasIPv6()) } else { stats.RecordPeerEvent(stats.ReapedLeech, peer.HasIPv6()) } } } } }
// 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 (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 }