269 lines
7.0 KiB
PHP
269 lines
7.0 KiB
PHP
<?php
|
|
namespace LaraBB\Tracker;
|
|
|
|
use LaraBB\Profile\Models\Profile;
|
|
use PerfectPurple\Models\TorrentPeer;
|
|
use PerfectPurple\Models\TorrentFile;
|
|
use stdClass;
|
|
|
|
//use PerfectPurple\Models\TorrentHistory;
|
|
|
|
class Announce {
|
|
|
|
/**
|
|
* @var
|
|
*/
|
|
public $config;
|
|
|
|
/**
|
|
* @var stdClass
|
|
*/
|
|
public $request;
|
|
|
|
private string $browsers = 'Mozilla|Chrome|Opera|Lynx|Trident|Edge';
|
|
|
|
/**
|
|
* @var
|
|
*/
|
|
private $currentPeer;
|
|
|
|
/**
|
|
* @var
|
|
*/
|
|
private $currentTorrent;
|
|
|
|
/**
|
|
* @var UserProfile
|
|
*/
|
|
private $userProfile;
|
|
|
|
/**
|
|
* @var TorrentPeer
|
|
*/
|
|
private $torrentPeer;
|
|
|
|
/**
|
|
* @var TorrentFile
|
|
*/
|
|
private $torrentFile;
|
|
//private $torrentHistory;
|
|
|
|
/**
|
|
* TorrentTracker constructor.
|
|
* @param UserProfile $userProfile
|
|
* @param TorrentPeer $torrentPeer
|
|
* @param TorrentFile $torrentFile
|
|
*/
|
|
public function __construct(
|
|
UserProfile $userProfile,
|
|
TorrentPeer $torrentPeer,
|
|
TorrentFile $torrentFile)
|
|
{
|
|
$this->config = config('perfectpurple.tracker');
|
|
$this->userProfile = $userProfile;
|
|
$this->torrentPeer = $torrentPeer;
|
|
$this->torrentFile = $torrentFile;
|
|
//$this->torrentHistory = $torrentHistory;
|
|
$this->request = new stdClass();
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function checkAccess(): bool
|
|
{
|
|
return !preg_match('/' . $this->browsers . '/', $this->request->agent);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function checkClientValues(): bool
|
|
{
|
|
return !empty($this->request->port);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function checkTorrent(): bool
|
|
{
|
|
if(empty($this->request->infoHash)) {
|
|
return false;
|
|
}
|
|
|
|
$this->currentTorrent = $this->torrentFile->readByInfoHash($this->request->infoHash);
|
|
|
|
return !is_null($this->currentTorrent);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function checkPid(): bool
|
|
{
|
|
$userProfile = $this->userProfile->readByPid($this->request->pid);
|
|
|
|
return !is_null($userProfile);
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function checkSamePid(): bool
|
|
{
|
|
$data = $this->torrentPeer->status($this->request->pid, $this->currentTorrent->id);
|
|
if(!$data->isEmpty()) {
|
|
foreach($data as $set) {
|
|
if($set->status == 'seeder' && $set->status_cnt >= $this->config['max_pid_seed']) return false;
|
|
if($set->status == 'leecher' && $set->status_cnt >= $this->config['max_pid_leech']) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @return $this
|
|
*/
|
|
public function checkFirewalled(): Announce
|
|
{
|
|
$theError = '';
|
|
$fd = fsockopen($this->request->ip, $this->request->port, $errno, $theError, 10);
|
|
|
|
$this->request->nat = !$fd;
|
|
fclose($fd);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return bool|string
|
|
*/
|
|
public function checkClientEvent(): bool|string
|
|
{
|
|
$this->currentPeer = $this->torrentPeer->read($this->request->pid, $this->currentTorrent->uuid, ['profile']);
|
|
|
|
return match ($this->request->event) {
|
|
'started' => $this->torrentStarted(),
|
|
'stopped' => $this->torrentStopped(),
|
|
'finished' => $this->torrentFinished(),
|
|
empty($this->currentRequest->event) => $this->torrentNoEvent(),
|
|
default => false,
|
|
};
|
|
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
private function torrentStarted(): string
|
|
{
|
|
if(!is_null($this->currentPeer)) {
|
|
$this->torrentPeer->edit($this->currentPeer, $this->request);
|
|
} else {
|
|
$this->torrentPeer->add($this->request, $this->currentTorrent);
|
|
$this->currentPeer = $this->torrentPeer;
|
|
}
|
|
|
|
/*$history = $this->torrentHistory->read($this->currentPeer->user->uid, $this->currentTorrent->id);
|
|
if(!is_null($history)) {
|
|
$this->torrentHistory->edit($history, $this->currentRequest, true);
|
|
} elseif(is_null($history) && $this->currentRequest->left > 0) {
|
|
$this->torrentHistory->add($this->currentPeer, $this->currentTorrent, $this->currentRequest, true);
|
|
}*/
|
|
|
|
$this->torrentFile->setSeedersLeechers($this->currentTorrent, $this->request);
|
|
return $this->getRandomPeers();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
private function torrentStopped(): string
|
|
{
|
|
$this->torrentPeer->kill($this->currentPeer, $this->currentTorrent);
|
|
$this->userProfile->setTraffic($this->currentPeer->profile, $this->request);
|
|
|
|
/*$history = $this->torrentHistory->read($this->currentPeer->user->uid, $this->currentTorrent->id);
|
|
if(!is_null($history)) {
|
|
$this->torrentHistory->edit($history, $this->currentRequest, false);
|
|
}*/
|
|
|
|
return $this->getRandomPeers();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
private function torrentFinished(): string
|
|
{
|
|
if(is_null($this->currentPeer)) {
|
|
$this->torrentPeer->add($this->request, $this->currentTorrent);
|
|
$this->currentPeer = $this->torrentPeer;
|
|
}
|
|
|
|
$this->torrentPeer->complete($this->currentPeer, $this->request);
|
|
$this->torrentFile->complete($this->currentTorrent);
|
|
|
|
/*$history = $this->torrentHistory->read($this->currentPeer->user->uid, $this->currentTorrent->id);
|
|
if(!is_null($history)) {
|
|
$this->torrentHistory->edit($history, $this->currentRequest, true, true);
|
|
} else {
|
|
$this->torrentHistory->add($this->currentPeer, $this->currentTorrent, $this->currentRequest, true, true);
|
|
}*/
|
|
|
|
return $this->getRandomPeers();
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
private function torrentNoEvent(): string
|
|
{
|
|
if(is_null($this->currentPeer)) {
|
|
$this->torrentPeer->add($this->request, $this->currentTorrent);
|
|
$this->currentPeer = $this->torrentPeer;
|
|
}
|
|
|
|
if($this->currentPeer->bytes != 0 && $this->request->left == 0) {
|
|
$this->torrentPeer->complete($this->currentPeer, $this->request);
|
|
$this->torrentFile->complete($this->currentTorrent);
|
|
}
|
|
|
|
$this->collectBytes();
|
|
|
|
return $this->getRandomPeers();
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
private function collectBytes(): void
|
|
{
|
|
$diff = bcsub($this->currentPeer->bytes, $this->currentPeer->left);
|
|
|
|
$this->torrentPeer->setBytes($this->currentPeer, $this->request, $diff);
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
private function getRandomPeers(): string
|
|
{
|
|
$data = $this->torrentPeer->random($this->currentTorrent->uuid, $this->request->numWant);
|
|
if(!is_null($data) && $this->request->compact) {
|
|
$compactStr = '';
|
|
$data->map(function($set) use(&$compactStr) {
|
|
$compactStr .= str_pad(pack('Nn', ip2long($set->ip), $set->port), 6);
|
|
});
|
|
|
|
return $compactStr;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|