seria/src/Torrents/TorrentPeers.php

143 lines
6.6 KiB
PHP

<?php
namespace Seria\Torrents;
use InvalidArgumentException;
use RuntimeException;
use Index\Data\DbStatementCache;
use Index\Data\IDbConnection;
use Seria\Users\UserInfo;
class TorrentPeers {
private IDbConnection $dbConn;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public function pruneExpiredPeers(): void {
$this->dbConn->execute('DELETE FROM ser_torrents_peers WHERE peer_expires < NOW()');
}
public function getPeers(TorrentInfo|string $torrentInfo): array {
$stmt = $this->cache->get('SELECT peer_id, torrent_id, user_id, INET6_NTOA(peer_address), peer_port, UNIX_TIMESTAMP(peer_updated), UNIX_TIMESTAMP(peer_expires), peer_agent, peer_key, peer_uploaded, peer_downloaded, peer_left FROM ser_torrents_peers WHERE torrent_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
$peers = [];
$result = $stmt->getResult();
while($result->next())
$peers[] = new TorrentPeerInfo($result);
return $peers;
}
public function getPeer(TorrentInfo|string $torrentInfo, string $peerId): ?TorrentPeerInfo {
$stmt = $this->cache->get('SELECT peer_id, torrent_id, user_id, INET6_NTOA(peer_address), peer_port, UNIX_TIMESTAMP(peer_updated), UNIX_TIMESTAMP(peer_expires), peer_agent, peer_key, peer_uploaded, peer_downloaded, peer_left FROM ser_torrents_peers WHERE torrent_id = ? AND peer_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->addParameter(2, $peerId);
$stmt->execute();
$result = $stmt->getResult();
if(!$result->next())
return null;
return new TorrentPeerInfo($result);
}
public function createPeer(
TorrentInfo|string $torrentInfo,
UserInfo|string|null $userInfo,
string $peerId,
string $remoteAddr,
int $remotePort,
int $interval,
string $peerAgent,
string $peerKey,
int $bytesUploaded,
int $bytesDownloaded,
int $bytesRemaining
): TorrentPeerInfo {
$stmt = $this->cache->get('INSERT INTO ser_torrents_peers (torrent_id, user_id, peer_id, peer_address, peer_port, peer_updated, peer_expires, peer_agent, peer_key, peer_uploaded, peer_downloaded, peer_left) VALUES (?, ?, ?, INET6_ATON(?), ?, NOW(), NOW() + INTERVAL ? SECOND, ?, ?, ?, ?, ?)');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->addParameter(2, $userInfo === null ? null : ($userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo));
$stmt->addParameter(3, $peerId);
$stmt->addParameter(4, $remoteAddr);
$stmt->addParameter(5, $remotePort);
$stmt->addParameter(6, $interval);
$stmt->addParameter(7, $peerAgent);
$stmt->addParameter(8, $peerKey);
$stmt->addParameter(9, $bytesUploaded);
$stmt->addParameter(10, $bytesDownloaded);
$stmt->addParameter(11, $bytesRemaining);
$stmt->execute();
return $this->getPeer($torrentInfo, $peerId) ?? throw new RuntimeException('Failed to record peer information.');
}
public function updatePeer(
TorrentInfo|string $torrentInfo,
TorrentPeerInfo|string $peerInfo,
string $remoteAddr,
int $remotePort,
int $interval,
string $peerAgent,
int $bytesUploaded,
int $bytesDownloaded,
int $bytesRemaining
): void {
$stmt = $this->cache->get('UPDATE ser_torrents_peers SET peer_address = INET6_ATON(?), peer_port = ?, peer_updated = NOW(), peer_expires = NOW() + INTERVAL ? SECOND, peer_agent = ?, peer_uploaded = ?, peer_downloaded = ?, peer_left = ? WHERE torrent_id = ? AND peer_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->addParameter(2, $peerInfo instanceof TorrentPeerInfo ? $peerInfo->getId() : $peerInfo);
$stmt->addParameter(3, $remoteAddr);
$stmt->addParameter(4, $remotePort);
$stmt->addParameter(5, $interval);
$stmt->addParameter(6, $peerAgent);
$stmt->addParameter(7, $bytesUploaded);
$stmt->addParameter(8, $bytesDownloaded);
$stmt->addParameter(9, $bytesRemaining);
$stmt->execute();
}
public function deletePeer(TorrentInfo|string $torrentInfo, TorrentPeerInfo|string $peerInfo): void {
$stmt = $this->cache->get('DELETE FROM ser_torrents_peers WHERE torrent_id = ? AND peer_id = ?');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->addParameter(2, $peerInfo instanceof TorrentPeerInfo ? $peerInfo->getId() : $peerInfo);
$stmt->execute();
}
public function countIncompletePeers(TorrentInfo|string $torrentInfo): int {
$stmt = $this->cache->get('SELECT COUNT(*) FROM ser_torrents_peers WHERE torrent_id = ? AND peer_left > 0');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
public function countCompletePeers(TorrentInfo|string $torrentInfo): int {
$stmt = $this->cache->get('SELECT COUNT(*) FROM ser_torrents_peers WHERE torrent_id = ? AND peer_left <= 0');
$stmt->addParameter(1, $torrentInfo instanceof TorrentInfo ? $torrentInfo->getId() : $torrentInfo);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
public function countUserDownloading(UserInfo|string $userInfo): int {
$stmt = $this->cache->get('SELECT COUNT(*) FROM ser_torrents_peers WHERE user_id = ? AND peer_left > 0');
$stmt->addParameter(1, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
public function countUserUploading(UserInfo|string $userInfo): int {
$stmt = $this->cache->get('SELECT COUNT(*) FROM ser_torrents_peers WHERE user_id = ? AND peer_left <= 0');
$stmt->addParameter(1, $userInfo instanceof UserInfo ? $userInfo->getId() : $userInfo);
$stmt->execute();
$result = $stmt->getResult();
return $result->next() ? $result->getInteger(0) : 0;
}
}