Example #1
0
// 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))
}
Example #2
0
// 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))
}