/ знакомства / игры / хостинг файлов / цитаты /

Автор Тема: Как создать свой торрент-трекер (torrent-tracker, аналог torrents.ru/rutracker)  (Прочитано 37768 раз)

Оффлайн admin

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 589
    • Просмотр профиля
    • Мириад
Бесплатные движки торрент-трекеров

TorrentPier

Один из самых популярных движков (русскоязычных и не только) BitTorrent-трекера. Выполнен в виде phpBB, сильно переписанного и расширенного до полноценного трекера. Полностью написан на PHP, включая анонсер. В основе организации лежит принцип торрент → топик, то есть торренту сопоставлена единственная тема на форме. Торрент-файл загружается в первое сообщение темы автором, после чего происходит регистрация этого торрента на трекере. Следует учесть, что хотя форумная и трекерная части достаточно тесно интегрированы, трекерная часть использует отдельные таблицы в БД, поэтому возможно отделить трекерную часть (анонсер) и вынести её, к примеру, на отдельный сервер.
http://code.google.com/p/torrentpier/


TBDev

Один из самых популярных (русскоязычных и не только) движков BitTorrent-трекера. Выполнен в виде системы управления содержимым. Полностью написан на PHP, включая анонсер. В основе организации лежит принцип новость → торрент или новость → торрент → релиз, то есть торренту сопоставлена определенное место на главной странице или отдельная страница с полным описанием и краткое сообщение о релизе на главной странице сайта. Торрент-файл загружается через специальную страницу, где пользователю предоставлено ввести описание, после чего происходит регистрация этого торрента на трекере. Существует много модификаций TBDev, самые популярные:


Extended BitTorrent
Торрент на C++ с хранением данных в MySQL
http://xbtt.sourceforge.net/


Kino KPK
CMS / торрент-трекер / индексатор торрентов. PHP+MySQL
http://dev.kinokpk.com/
https://github.com/ZonD80/Kinokpk.com-releaser


ppkBB3cker
мод торрент трекера для форума phpBB3
http://www.ppkbb3cker.ru/
http://gitorious.org/xbtbb3cker


Bittorrent Tracker for SMF
Модификация для форума SMF (Simple Machines) Работает для версий позже SMF 2.0 RC4
http://www.simplemachines.org/community/index.php?topic=239603.0
« Последнее редактирование: 01 Января 2011, 09:40:00 от admin »

Оффлайн admin

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 589
    • Просмотр профиля
    • Мириад
Bitstorm

Простейший торрент-трекер, рассчитан, максимум, на 1000 пиров.


https://ck3r.org/tracker/ui.php

Исходный код:
Цитировать
<?php
/*
* Bitstorm - A small and fast Bittorrent tracker
* Copyright 2008 Peter Caprioli
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

 /*************************
 ** Configuration start **
 *************************/

//Enable debugging?
//This allows anyone to see the entire peer database by appending ?debug to the announce URL
define('__DEBUGGING_ON', false);

//What version are we at?
define('__VERSION', 1.3);

//How often should clients pull server for new clients? (Seconds)
define('__INTERVAL', 1800);

//What's the minimum interval a client may pull the server? (Seconds)
//Some bittorrent clients does not obey this
define('__INTERVAL_MIN', 300);

//How long should we wait for a client to re-announce after the last
//announce expires? (Seconds)
define('__CLIENT_TIMEOUT', 60);

//Skip sending the peer id if client does not want it?
//Hint: Should be set to true
define('__NO_PEER_ID', true);

//Should seeders not see each others?
//Hint: Should be set to true
define('__NO_SEED_P2P', true);

//Where should we save the peer database
//On Linux, you should use /dev/shm as it is very fast.
//On Windows, you will need to change this value to some
//other valid path such as C:/Peers.txt
define('__LOCATION_PEERS', '/dev/shm/Bittorrent.Peers');

//Should we enable short announces?
//This allows NATed clients to get updates much faster, but it also
//takes more load on the server.
//(This is just an experimental feature which may be turned off)
define('__ENABLE_SHORT_ANNOUNCE', true);

//In case someone tries to access the tracker using a browser,
//redirect to this URL or file
define('__REDIR_BROWSER', './ui.php');

 /***********************
 ** Configuration end **
 ***********************/

//Send response as text
header('Content-type: Text/Plain');
header('X-Tracker-Version: Bitstorm '.__VERSION.' by ck3r.org'); //Please give me some credit
                         //If you *really* dont want to, comment this line out
//Bencoding function, returns a bencoded dictionary
//You may go ahead and enter custom keys in the dictionary in
//this function if you'd like.
function track($list, $interval=60, $min_ival=0) {
   if (is_string($list)) { //Did we get a string? Return an error to the client
      return 'd14:failure reason'.strlen($list).':'.$list.'e';
   }
   $p = ''; //Peer directory
   $c = $i = 0; //Complete and Incomplete clients
   foreach($list as $d) { //Runs for each client
      if ($d[7]) { //Are we seeding?
         $c++; //Seeding, add to complete list
         if (__NO_SEED_P2P && is_seed()) { //Seeds should not see each others
            continue;
         }
      } else {
         $i++; //Not seeding, add to incomplete list
      }
      //Do some bencoding
      
      $pid = '';
      
      if (!isset($_GET['no_peer_id']) && __NO_PEER_ID) { //Shall we include the peer id
         $pid = '7:peer id'.strlen($d[1]).':'.$d[1];
      }
      
      $p .= 'd2:ip'.strlen($d[0]).':'.$d[0].$pid.'4:porti'.$d[2].'ee';
   }
   //Add some other paramters in the dictionary and merge with peer list
   $r = 'd8:intervali'.$interval.'e12:min intervali'.$min_ival.'e8:completei'.$c.'e10:incompletei'.$i.'e5:peersl'.$p.'ee';
   return $r;
}

//Find out if we are seeding or not. Assume not if unknown.
function is_seed() {
   if (!isset($_GET['left'])) {
      return false;
   }
   if ($_GET['left'] == 0) {
      return true;
   }
   return false;
}

/*
* Yeah, this is the database engine. It's pretty bad, uses files to store peers.
* Should be easy to rewrite to use SQL instead.
*
* Yes, sometimes collisions may occur and screw the DB over. It might or might not
* recover by itself.
*/

//Save database to file
function db_save($data) {
   $b = serialize($data);
   $h = @fopen(__LOCATION_PEERS, 'w');
   if (!$h) { return false; }
   if (!@flock($h, LOCK_EX)) { return false; }
   @fwrite($h, $b);
   @fclose($h);
   return true;
}

//Load database from file
function db_open() {
   $p = '';
   $m = '';
   $h = @fopen(__LOCATION_PEERS, 'r');
   if (!$h) { return false; }
   if (!@flock($h, LOCK_EX)) { return false; }
   while (!@feof($h)) {
      $p .= @fread($h, 512);
   }
   @fclose($h);
   return unserialize($p);
}

//Check if DB file exists, otherwise create it
function db_exists($create_empty=false) {
   if (file_exists(__LOCATION_PEERS)) {
      return true;
   }
   if ($create_empty) {
      if (!db_save(array())) {
         return false;
      }
      return true;
   }
   return false;
}

//Default announce time
$interval = __INTERVAL;

//Minimal announce time (does not apply to short announces)
$interval_min = __INTERVAL_MIN;

/*
* This is a pretty smart feature not present in other tracker software.
* If you expect to have many NATed clients, add short as a GET parameter,
* and clients will pull much more often.
*
* This can be done automatically, simply try to open a TCP connection to
* the client and assume it is NATed if not successful.
*/
if (isset($_GET['short']) && __ENABLE_SHORT_ANNOUNCE) {
   $interval = 120;
   $interval_min = 30;
}

//Did we get any parameters at all?
//Client is  probably a web browser, do a redirect
if (empty($_GET)) {
   header('Location: '.__REDIR_BROWSER);
   die();
}

//Create database if it does not exist
db_exists(true) or die(track('Unable to create database'));
$d = db_open();

//Do we want to debug? (Should not be used by default)
if (isset($_GET['debug']) && __DEBUGGING_ON) {
   echo 'Connected peers:'.count($d)."\n\n";
   print_r($d);
   die();
}

//Did we get a failure from the database?
if ($d === false) {
   die(track('Database failure'));
}

//Do some input validation
function valdata($g, $must_be_20_chars=false) {
   if (!isset($_GET[$g])) {
      die(track('Missing one or more arguments'));
   }
   if (!is_string($_GET[$g])) {
      die(track('Invalid types on one or more arguments'));
   }
   if ($must_be_20_chars && strlen($_GET[$g]) != 20) {
      die(track('Invalid length on '.$g.' argument'));
   }
   if (strlen($_GET[$g]) > 128) { //128 chars should really be enough
      die(track('Argument '.$g.' is too large to handle'));
   }
}

//Inputs that are needed, do not continue without these
valdata('peer_id', true);
valdata('port');
valdata('info_hash', true);

//Use the tracker key extension. Makes it much harder to steal a session.
if (!isset($_GET['key'])) {
   $_GET['key'] = '';
}
valdata('key');

//Do we have a valid client port?
if (!ctype_digit($_GET['port']) || $_GET['port'] < 1 || $_GET['port'] > 65535) {
   die(track('Invalid client port'));
}

//Array key, unique for each client and torrent
$sum = sha1($_GET['peer_id'].$_GET['info_hash']);

//Make sure we've got a user agent to avoid errors
//Used for debugging
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
   $_SERVER['HTTP_USER_AGENT'] = ''; //Must always be set
}

//When should we remove the client?
$expire = time()+$interval;

//Have this client registered itself before? Check that it uses the same key
if (isset($d[$sum])) {
   if ($d[$sum][6] !== $_GET['key']) {
      sleep(3); //Anti brute force
      die(track('Access denied, authentication failed'));
   }
}

//Add/update the client in our global list of clients, with some information
$d[$sum] = array($_SERVER['REMOTE_ADDR'], $_GET['peer_id'], $_GET['port'], $expire, $_GET['info_hash'], $_SERVER['HTTP_USER_AGENT'], $_GET['key'], is_seed());

//No point in saving the user agent, unless we are debugging
if (!__DEBUGGING_ON) {
   unset($d[$sum][5]);
} elseif (!empty($_GET)) { //We are debugging, add GET parameters to database
   $d[$sum]['get_parm'] = $_GET;
}

//Did the client stop the torrent?
//We dont care about other events
if (isset($_GET['event']) && $_GET['event'] === 'stopped') {
   unset($d[$sum]);
   db_save($d);
   die(track(array())); //The RFC says its OK to return whatever we want when the client stops downloading,
                             //however, some clients will complain about the tracker not working, hence we return
                             //an empty bencoded peer list
}

//Check if any client timed out
foreach($d as $k => $data) {
   if (time() > $data[3]+__CLIENT_TIMEOUT) { //Give the client some extra time before timeout
      unset($d[$k]); //Client has gone away, remove it
   }
}

//Save the client list
db_save($d);

//Compare info_hash to the rest of our clients and remove anyone who does not have the correct torrent
foreach($d as $id => $info) {
   if ($info[4] !== $_GET['info_hash']) {
      unset($d[$id]);
   }
}

//Remove self from list, no point in having ourselfes in the client dictionary
unset($d[$sum]);

//Add a few more seconds on the timeout to balance the load
$interval += rand(0, 10);

//Bencode the dictionary and send it back
die(track($d, $interval, $interval_min));
?>