announce handle dual

This commit is contained in:
xiaomlove
2022-04-20 15:29:12 +08:00
parent 7a79673669
commit 541f0eb46f

View File

@@ -34,6 +34,10 @@ class TrackerRepository extends BaseRepository
const MUST_BE_CHEATER_SPEED = 1024 * 1024 * 1024; //1024 MB/s const MUST_BE_CHEATER_SPEED = 1024 * 1024 * 1024; //1024 MB/s
const MAY_BE_CHEATER_SPEED = 1024 * 1024 * 100; //100 MB/s const MAY_BE_CHEATER_SPEED = 1024 * 1024 * 100; //100 MB/s
const ANNOUNCE_FIRST = 0;
const ANNOUNCE_DUAL = 1;
const ANNOUNCE_DUPLICATE = 2;
// Port Blacklist // Port Blacklist
protected const BLACK_PORTS = [ protected const BLACK_PORTS = [
22, // SSH Port 22, // SSH Port
@@ -63,8 +67,8 @@ class TrackerRepository extends BaseRepository
$user = $this->checkUser($request); $user = $this->checkUser($request);
$clientAllow = $this->checkClient($request); $clientAllow = $this->checkClient($request);
$torrent = $this->checkTorrent($queries, $user); $torrent = $this->checkTorrent($queries, $user);
if ($this->isReAnnounce($request, $queries['ip']) === false) { $isReAnnounce = $this->isReAnnounce($request);
$withPeers = true; if ($isReAnnounce < self::ANNOUNCE_DUPLICATE) {
/** @var Peer $peerSelf */ /** @var Peer $peerSelf */
$peerSelf = $this->checkMinInterval($torrent, $queries, $user); $peerSelf = $this->checkMinInterval($torrent, $queries, $user);
$isPeerExists = true; $isPeerExists = true;
@@ -91,32 +95,36 @@ class TrackerRepository extends BaseRepository
$this->checkCheater($torrent, $dataTraffic, $user, $peerSelf); $this->checkCheater($torrent, $dataTraffic, $user, $peerSelf);
} }
/**
* Note: Must update snatch first, otherwise peer `last_action` already change
*/
$snatch = $this->updateSnatch($peerSelf, $queries, $dataTraffic);
if ($queries['event'] == 'completed') {
$this->handleHitAndRun($user, $torrent, $snatch);
}
/** /**
* Note: Must update peer first, otherwise updateTorrent() count peer not correct * Note: Must update peer first, otherwise updateTorrent() count peer not correct
* Update: Will not change $peerSelf any more
*/ */
$this->updatePeer($peerSelf, $queries); $this->updatePeer($peerSelf, $queries);
$this->updateTorrent($torrent, $queries, $isPeerExists); if ($isReAnnounce === self::ANNOUNCE_FIRST) {
$withPeers = true;
/**
* Note: Must update snatch first, otherwise peer `last_action` already change
*/
$snatch = $this->updateSnatch($peerSelf, $queries, $dataTraffic);
if ($queries['event'] == 'completed') {
$this->handleHitAndRun($user, $torrent, $snatch);
}
if ($dataTraffic['uploaded_increment_for_user'] > 0) { $this->updateTorrent($torrent, $queries, $isPeerExists);
$this->userUpdates['uploaded'] = DB::raw('uploaded + ' . $dataTraffic['uploaded_increment_for_user']);
} if ($dataTraffic['uploaded_increment_for_user'] > 0) {
if ($dataTraffic['downloaded_increment_for_user'] > 0) { $this->userUpdates['uploaded'] = DB::raw('uploaded + ' . $dataTraffic['uploaded_increment_for_user']);
$this->userUpdates['downloaded'] = DB::raw('downloaded + ' . $dataTraffic['downloaded_increment_for_user']); }
} if ($dataTraffic['downloaded_increment_for_user'] > 0) {
if ($user->clientselect != $clientAllow->id) { $this->userUpdates['downloaded'] = DB::raw('downloaded + ' . $dataTraffic['downloaded_increment_for_user']);
$this->userUpdates['clientselect'] = $clientAllow->id; }
} if ($user->clientselect != $clientAllow->id) {
if ($user->showclienterror == 'yes') { $this->userUpdates['clientselect'] = $clientAllow->id;
$this->userUpdates['showclienterror'] = 'no'; }
if ($user->showclienterror == 'yes') {
$this->userUpdates['showclienterror'] = 'no';
}
} }
} }
$repDict = $this->generateSuccessAnnounceResponse($torrent, $queries, $user, $withPeers); $repDict = $this->generateSuccessAnnounceResponse($torrent, $queries, $user, $withPeers);
@@ -133,15 +141,8 @@ class TrackerRepository extends BaseRepository
do_log("[" . get_class($exception) . "] " . $exception->getMessage() . "\n" . $exception->getTraceAsString(), 'error'); do_log("[" . get_class($exception) . "] " . $exception->getMessage() . "\n" . $exception->getTraceAsString(), 'error');
$repDict = $this->generateFailedAnnounceResponse("system error, report to sysop please, hint: " . nexus()->getRequestId()); $repDict = $this->generateFailedAnnounceResponse("system error, report to sysop please, hint: " . nexus()->getRequestId());
} finally { } finally {
if (isset($user) && count($this->userUpdates)) { if (isset($user)) {
$user->fill($this->userUpdates); $this->updateUser($user);
$willBeUpdate = "[USER_ACTUAL_UPDATE] user: " . $user->id;
foreach ($user->getDirty() as $key => $value) {
$willBeUpdate .= ", $key = $value";
}
do_log($willBeUpdate);
$user->save();
do_log(last_query());
} }
return $this->sendFinalAnnounceResponse($repDict); return $this->sendFinalAnnounceResponse($repDict);
} }
@@ -548,21 +549,29 @@ class TrackerRepository extends BaseRepository
} }
} }
protected function isReAnnounce(Request $request, $ip): bool protected function isReAnnounce(Request $request): int
{ {
$key = $request->query->get('key'); $key = $request->query->get('key');
$queryString = $request->getQueryString(); $queryString = $request->getQueryString();
$lockKeyOriginal = str_replace($key, '', $queryString); $lockKeyOriginal = str_replace($key, '', $queryString);
$lockKeyOriginal .= "&__ip=" . $ip;
$lockKey = md5($lockKeyOriginal); $lockKey = md5($lockKeyOriginal);
$startTimestamp = nexus()->getStartTimestamp(); $startTimestamp = nexus()->getStartTimestamp();
do_log("key: $key, queryString: $queryString, lockKeyOriginal: $lockKeyOriginal, startTimestamp: $startTimestamp"); do_log("key: $key, queryString: $queryString, lockKeyOriginal: $lockKeyOriginal, startTimestamp: $startTimestamp");
$redis = Redis::connection()->client(); $redis = Redis::connection()->client();
if (!$redis->set($lockKey, $startTimestamp, ['nx', 'ex' => 5])) { $cache = $redis->get($lockKey);
do_log('[RE_ANNOUNCE]'); if ($cache === false) {
return true; //new request
$redis->set($lockKey, $startTimestamp, ['ex' => self::MIN_ANNOUNCE_WAIT_SECOND]);
return self::ANNOUNCE_FIRST;
} else {
if (bcsub($startTimestamp, $cache, 3) < 0.5) {
do_log('[DUAL]');
return self::ANNOUNCE_DUAL;
} else {
do_log('[RE_ANNOUNCE]');
return self::ANNOUNCE_DUPLICATE;
}
} }
return false;
} }
private function generateSuccessAnnounceResponse($torrent, $queries, $user, $withPeers = true): array private function generateSuccessAnnounceResponse($torrent, $queries, $user, $withPeers = true): array
@@ -728,6 +737,7 @@ class TrackerRepository extends BaseRepository
* *
* @param Torrent $torrent * @param Torrent $torrent
* @param $queries * @param $queries
* @param bool $isPeerExists
*/ */
private function updateTorrent(Torrent $torrent, $queries, bool $isPeerExists) private function updateTorrent(Torrent $torrent, $queries, bool $isPeerExists)
{ {
@@ -940,15 +950,8 @@ class TrackerRepository extends BaseRepository
do_log("[" . get_class($exception) . "] " . $exception->getMessage() . "\n" . $exception->getTraceAsString(), 'error'); do_log("[" . get_class($exception) . "] " . $exception->getMessage() . "\n" . $exception->getTraceAsString(), 'error');
$repDict = $this->generateFailedAnnounceResponse("system error, report to sysop please, hint: " . nexus()->getRequestId()); $repDict = $this->generateFailedAnnounceResponse("system error, report to sysop please, hint: " . nexus()->getRequestId());
} finally { } finally {
if (isset($user) && count($this->userUpdates)) { if (isset($user)) {
$user->fill($this->userUpdates); $this->updateUser($user);
$willBeUpdate = "[USER_ACTUAL_UPDATE] user: " . $user->id;
foreach ($user->getDirty() as $key => $value) {
$willBeUpdate .= ", $key = $value";
}
do_log($willBeUpdate);
$user->save();
do_log(last_query());
} }
return $this->sendFinalAnnounceResponse($repDict); return $this->sendFinalAnnounceResponse($repDict);
} }
@@ -1030,4 +1033,13 @@ class TrackerRepository extends BaseRepository
DB::insert($sql); DB::insert($sql);
} }
private function updateUser(User $user)
{
if (count($this->userUpdates) === 0) {
return;
}
$user->save($this->userUpdates);
do_log(last_query());
}
} }