From a0c2ddfd1b93037f73bac751866ea2a81c3f3984 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Sun, 3 Apr 2022 18:12:04 +0300 Subject: [PATCH] implemented UDP tracker protocol & re-tracker proxy-announcing for UDP --- tracker.php | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/tracker.php b/tracker.php index e943096..49d1947 100644 --- a/tracker.php +++ b/tracker.php @@ -2,8 +2,6 @@ require("../php/config.php"); require("bencoder.php"); require("peer.php"); -$ANN_USERAGENT = "Transmission/3.00"; -$ANN_PEER_ID = "01234567890123456789"; $DB_NAME = "torrent"; class Tracker { @@ -34,7 +32,7 @@ class Tracker { return false; } - public function doHttpAnnounce($infoHash, $peerIp, $peerPort, $peerId = null, $uploaded = 0, $downloaded = 0, $left = 0) { + protected function doHttpAnnounce($infoHash, $peerIp, $peerPort, $peerId = null, $uploaded = 0, $downloaded = 0, $left = 0) { $peers = array(); $passkey = is_null($this->passkey) ? "" : $this->passkey . "&"; @@ -80,9 +78,57 @@ class Tracker { return $peers; } + protected function doUdpAnnounce($infoHash, $peerIp, $peerPort, $peerId = null, $uploaded = 0, $downloaded = 0, $left = 0) { + $peers = array(); + + $addr = gethostbyname($this->host); + $port = $this->port; + $key = 0; + + $sockfd = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + socket_set_option($sockfd, SOL_SOCKET, SO_RCVTIMEO, + array("sec" => 1, "usec" => 0)); + + $transaction_id = rand(); + $req = pack("JNN", 4497486125440, 0, $transaction_id); + socket_sendto($sockfd, $req, 16, 0, $addr, $port); + $recv = socket_recvfrom($sockfd, $buf, 16, 0, $addr, $port); + if ($recv == false || $recv == 0) { + return false; + } + $res = unpack("Naction/Ntransaction_id/Jconnection_id", $buf); + $connection_id = $res["connection_id"]; + + $transaction_id = rand(); + $req = pack("JNN", $connection_id, 1, $transaction_id) + . hex2bin($infoHash) + . (is_null($peerId) ? self::ANN_PEER_ID : $peerId) + . pack("JJJNNNNn", $downloaded, $uploaded, $left, + 0, $peerIp, $key, -1, $peerPort); + socket_sendto($sockfd, $req, 98, 0, $addr, $port); + $recv = socket_recvfrom($sockfd, $buf, 65535, 0, $addr, $port); + if ($recv == false || $recv == 0) { + return false; + } + $res = unpack("Naction/Ntransaction_id/Ninterval/Nleechers/Nseeders", $buf); + //$count = $res["leechers"] + $res["seeders"]; + $count = ($res - 20) / 6; + for ($i = 0; $i < $count; $i++) { + $peer = unpack("Nip/nport", $buf, 20 + $i*6); + array_push($peers, new Peer($infoHash, + long2ip($peer["ip"]), $peer["port"])); + } + + socket_close($sockfd); + + return $peers; + } + public function announce($infoHash, $peerIp, $peerPort, $peerId = null, $uploaded = 0, $downloaded = 0, $left = 0) { if ($this->proto == "http" || $this->proto == "https") { return $this->doHttpAnnounce($infoHash, $peerIp, $peerPort, $peerId, $uploaded, $downloaded, $left); + } else if ($this->proto == "udp") { + return $this->doUdpAnnounce($infoHash, $peerIp, $peerPort, $peerId, $uploaded, $downloaded, $left); } return false;