Guest User

One File Tracker

a guest
Feb 26th, 2011
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 8.21 KB | None | 0 0
  1. <?php
  2. /* One-file(+MySQL) BitTorrent Tracker
  3.  * Written by kenkeiras
  4.  *
  5.  * This program is free software. It comes without any warranty, to
  6.  * the extent permitted by applicable law. You can redistribute it
  7.  * and/or modify it under the terms of the Do What The Fuck You Want
  8.  * To Public License, Version 2, as published by Sam Hocevar. See
  9.  * http://sam.zoy.org/wtfpl/COPYING for more details. */
  10.  
  11. /* MySQL database configuration */
  12. /* Database host */
  13. $dbhost = 'localhost';
  14.  
  15. /* Database user */
  16. $dbuser = "one_file_tracker";
  17.  
  18. /* Database password */
  19. $dbpass = "one_file_tracker";
  20.  
  21. /* Database name */
  22. $dbname = "one_file_tracker";
  23.  
  24. /* Entry timeout (in seconds)
  25.  * after this time, peer data will be no longer sended
  26.  */
  27. $timeout = 3600;
  28.  
  29. /* Peer table name
  30.  * Columns:
  31.  *  Peer_id: char(28)
  32.  *  info_hash: char(28)
  33.  *  port: smallint unsigned
  34.  *  uploaded: int(1)
  35.  *  downloaded: int(1)
  36.  *  to_go: int(1)
  37.  *  ip: varchar(15)
  38.  *  peer_key: varchar(255)
  39.  *  completed: boolean
  40.  *  last_update: int(1)
  41.  *
  42.  * Keys:
  43.  *  Peer_id
  44.  *  info_hash
  45.  *
  46.  * create table peers( peer_id char(28), info_hash char(28), port smallint
  47.  *             unsigned, uploaded int(1), downloaded int(1), to_go int(1),
  48.  *               ip varchar(15), peer_key varchar(255), completed boolean,
  49.  *                     last_update int(1),KEY (peer_id), KEY (info_hash));
  50.  */
  51. $dbtable = "peers";
  52.  
  53. /* Default number of peers returned
  54.  *  protocol's default is 50
  55.  */
  56. $default_peer_num = 50;
  57.  
  58. /* Interval in seconds that the client should wait between
  59.  * sending regular requests to the tracker
  60.  */
  61. $interval = 300;
  62.  
  63. /* Max peer returned */
  64. $max_peer_num = 100;
  65.  
  66. /* Prints a number in network order */
  67. function hton_spwn($n, $c){
  68.     for($i=$c-1;$i>=0;$i--){
  69.         echo chr($n>>($i*8));
  70.         $n = $n % (1<<($i*8));
  71.     }
  72. }
  73.  
  74. /* Sends an error in the BitTorrent'ish way */
  75. function bt_die($s){
  76.     $fail="failure reason";
  77.     die( "d".strlen($fail).":".$fail.strlen($s).$s."e" );
  78. }
  79.  
  80. /* Sends the peer list */
  81. function send_bencoded_peers($d){
  82.     print "d";
  83.     $int = "interval"; // Connection interval
  84.     echo strlen($int).":".$int."i".$d['interval']."e";
  85.  
  86.     if (!$d['stop']){
  87.         $comp = "complete"; // Seeds
  88.         echo strlen($comp).":".$comp."i".$d['complete']."e";
  89.  
  90.         $incomp = "incomplete"; // Leechers
  91.         echo strlen($incomp).":".$incomp."i".$d['incomplete']."e";
  92.     }
  93.  
  94.     $peers = "peers";
  95.     echo strlen($peers).":$peers"; // Peer list
  96.     $has_peers = FALSE;
  97.     if ($d['compact']){
  98.         echo (6 * mysql_num_rows($d['peers']) ).":";
  99.     }
  100.     else{
  101.         echo "l";
  102.     }
  103.     while ( ($n = mysql_fetch_array($d['peers'])) !== FALSE ){
  104.         $has_peers = TRUE;
  105.         if ($d['compact']){ // Compact format
  106.             echo hton_spwn(ip2long($n['ip']),4);
  107.             echo hton_spwn($n['port'],2);
  108.         }
  109.         else{ // Normal format
  110.             $url_peer = urlencode($n['peer_id']);
  111.             echo "d";
  112.             if (strlen($url_peer) > 0){
  113.                 echo "2:id".strlen($url_peer).":".$url_peer;
  114.             }
  115.             echo "2:ip".strlen($n['ip']).":".$n['ip'];
  116.             echo "4:port".strlen($n['port']).":".$n['port']."e";
  117.         }
  118.     }
  119.     if (!$d['compact']){
  120.         echo "e";
  121.     }
  122.     echo "e";
  123. }
  124.  
  125. /* The true tracker function */
  126. function tracker($dbhost, $dbuser,$dbpass,$dbname,$dbtable){
  127.  
  128.     header('Content-type: text/plain');
  129.  
  130.     $db = mysql_connect( $dbhost, $dbuser, $dbpass ) or
  131.                               bt_die("Error connecting to database");
  132.    
  133.     mysql_select_db( "$dbname", $db ) or
  134.                                 bt_die("Error selecting a database");
  135.  
  136.     /* Delete timeouted peers */
  137.     mysql_query( "delete from $dbtable where ".
  138.                 "last_update<".(time()-$GLOBALS['timeout']).";") or
  139.                                     bt_die("Error updating database");
  140.  
  141.     /* SQL-safe values */
  142.     $peer_id = base64_encode($_GET['peer_id']);
  143.     $info_hash = base64_encode($_GET['info_hash']);
  144.     $port = intval($_GET['port']);
  145.     $uploaded = intval($_GET['uploaded']);
  146.     $downloaded = intval($_GET['downloaded']);
  147.     $to_go = intval($_GET['left']);
  148.     $ip = $_SERVER['REMOTE_ADDR'];
  149.     $peer_key = base64_encode($_GET['key']);
  150.     $stopping = FALSE;
  151.  
  152.     /* Checks if it needs to add or just update the rows */
  153.     $res = mysql_query( "select count(1) as count from $dbtable where ".
  154.                 "peer_id='$peer_id' and info_hash='$info_hash';") or
  155.                                     bt_die("Error reading database");
  156.  
  157.     $num = mysql_fetch_array($res);
  158.     if ( isset( $_GET['event'])&&($_GET['event']=="stopped")){
  159.         mysql_query("delete from $dbtable ".
  160.                    "where peer_id='$peer_id' and info_hash='$info_hash'".
  161.                    "and peer_key='$peer_key';") or
  162.                      bt_die( "Error deleting you from available peers");
  163.         $stopping = TRUE;
  164.     }
  165.     $state = "";
  166.     if ((isset($_GET['event'])&&($_GET['event']=="completed"))
  167.          or ($to_go < 1)){
  168.  
  169.         $state = ",completed=true";
  170.     }
  171.     elseif (isset($_GET['event'])&&($_GET['event']=="started")){
  172.         $state = ",completed=false";
  173.     }
  174.  
  175.     if ( !$stopping ){
  176.         /* Stores the data */
  177.         if ( $num['count'] == 0 ){
  178.             mysql_query( "insert into $dbtable set ".
  179.                     "last_update=".time().",".
  180.                     "peer_id='$peer_id',info_hash='$info_hash',".
  181.                     "uploaded=$uploaded,peer_key='$peer_key',".
  182.                     "downloaded=$downloaded,to_go=$to_go,ip='$ip',".
  183.                     "port=$port $state;") or
  184.                         bt_die( "Error adding you to the peer database");
  185.         }
  186.         else{
  187.             mysql_query( "update $dbtable set uploaded=$uploaded,".
  188.                     "last_update=".time().",".
  189.                     " downloaded=$downloaded,to_go=$to_go,ip='$ip', ".
  190.                     "port=$port $state ".
  191.                     "where peer_id='$peer_id' and info_hash='$info_hash' ".
  192.                     "and peer_key='$peer_key';") or
  193.                                        bt_die("Error updating database");
  194.         }
  195.     }
  196.     /* Reads the total number of peers */
  197.     $res = mysql_fetch_array(mysql_query("select count(1) as count ".
  198.                                      " from $dbtable ".
  199.                                      " where info_hash='$info_hash';"));
  200.  
  201.     $total_peers = $res['count'];
  202.     $peerNum = $GLOBALS["default_peer_num"];
  203.     if ( isset( $_GET['numwant'] ) &&
  204.                         $_GET['numwant'] <= $GLOBALS['max_peer_num']){
  205.  
  206.         $peerNum = $_GET['numwant'];
  207.     }
  208.     $top = $total_peers > $peerNum?$total_peers - $peerNum:0;
  209.     $off = rand(0, $top);
  210.  
  211.     /* Takes some random peers */
  212.     $peers = mysql_query("select peer_id,ip,port".
  213.                          " from $dbtable ".
  214.                          " where peer_id!='$peer_id'".
  215.                          " and info_hash='$info_hash' ".
  216.                          " limit $off,$peerNum;");
  217.  
  218.     /* Reads how many of the hava completed the download */
  219.     $comp = mysql_fetch_array(mysql_query("select count(1) as count ".
  220.                                         " from $dbtable ".
  221.                                         " where info_hash='$info_hash' and".
  222.                                         " peer_id!='$peer_id' and ".
  223.                                         " completed=True ;"));
  224.     /* Stores all in a dictionary */
  225.     $dict = array( 'interval'=> $GLOBALS['interval']."",
  226.                    'complete'=> $comp['count'],
  227.                    'incomplete'=> $total_peers - $comp['count'],
  228.                    'peers' => $peers,
  229.                    'compact' => isset($_GET['compact']) &&
  230.                                     ($_GET['compact'] == "1")?TRUE:FALSE,
  231.                    'stop' => $stopping);
  232.  
  233.     /* And sends it */
  234.     send_bencoded_peers($dict);
  235.  
  236.     mysql_close();
  237. }
  238.  
  239. if (isset($_GET) && isset($_GET['peer_id']) && isset($_GET['peer_id'])){
  240.     tracker($dbhost, $dbuser,$dbpass,$dbname,$dbtable);
  241. }
  242. else{
  243.     echo  <<< __EOF__
  244. <html><head><title>One File Tracker</title></head>
  245. <body>Are you a BitTorrent client? &not;&not;</body></html>
  246. __EOF__;
  247.  
  248. }
  249. ?>
Add Comment
Please, Sign In to add comment