0xFFFF) ) bt_error('Invalid port: '. $request['port']); // uploaded $request['uploaded'] = (int)$request['uploaded']; // downloaded $request['downloaded'] = (int)$request['downloaded']; // left $request['left'] = (int)$request['left']; // event if (array_key_exists('event', $request)) { switch (strtolower(stripslashes($request['event']))) { case 'started': case 'stopped': case 'completed': case '': break; default: $request['event'] = ''; } $request['event'] = strtolower(stripslashes($request['event'])); } else { $request['event'] = ''; } // numwant if (!array_key_exists('numwant', $request)) { foreach (array('num want', 'num_want') as $key) { if (array_key_exists($key, $request)) { $request['numwant'] = 0 + $request[$key]; unset($request[$key]); break; } } } if (array_key_exists('numwant', $request)) { if ($request['numwant'] == 0) { $request['numwant'] = 30; } } else { $request['numwant'] = 30; } // trackerid if (array_key_exists('trackerid', $request)) { $request['trackerid'] = strtolower(stripslashes($request['trackerid'])); } else { $request['trackerid'] = $_tracker_name .'-'. $_tracker_version; } /* ************************************************************************ */ /* ******************** DONE EVALUATING GET PARAMETERS ******************** */ /* ************************************************************************ */ // Set default values $uid = 0; // Lookup the torrent $torrent = db_fetch_object(db_query("SELECT fid FROM {bt_torrents} WHERE info_hash = '%s'", $request['info_hash'])); if(!empty($torrent)) { $request['fid'] = $torrent->fid; } else { bt_error('Torrent does not exist, please consider uploading it.'); } // Save current announce time to use the same value in all queries and calculations $request['current_announce'] = time(); // Start the generating the response. if ($_tracker_scope == 2) { // Lookup the user and validate permission to use the tracker. $uid = db_result(db_query("SELECT uid FROM {bt_tracker_users} WHERE passkey = '%s'", $request['passkey'])); if (empty($uid)) { bt_error('Passkey does not exist please re-download torrent.'); } // Determine if the user has permission to use the tracker. $user = user_load(array('uid' => $uid)); if (!user_access('download torrent', $user)) { bt_error('User does not have permission to user the tracker.'); } // Check to make sure the user meets minimum requirements //TODO: also use IP, client_id, ... if ($_maximum_simultaneous_downloads != 0) { $connection_count = db_result(db_query("SELECT COUNT(uid) FROM {bt_tracker_connections} WHERE uid = %d", $uid)); if ($connection_count > $_maximum_simultaneous_downloads) { bt_error('Too many simultaneous downloads, the limit is '. $_maximum_simultaneous_downloads); } } if ($_minimum_ratio) { $ratio = db_result(db_query("SELECT bytes_downloaded / bytes_uploaded FROM {bt_tracker_users} WHERE uid = %d")); if (!$ratio) { $ratio = 0; } } // Verify that the user has achieved the minimum ratio if ($_minimum_ratio && $ratio < $_minimum_ratio) { bt_error('Minimum ratio has not been met, you have '. $ratio .', and you need '. $_minimum_ratio); } // Passkey is marked for reset $passkey_status = db_result(db_query("SELECT passkey_status FROM {bt_tracker_users} WHERE passkey = '%s'", $request['passkey'])); if ($passkey_status == 1) { bt_error("Passkey is marked for reset, please re-download your torrents."); } else { // Check if there are two peers (distinct IP) downloading with the same passkey $distinct_ip_connection_count = db_result(db_query("SELECT COUNT(DISTINCT btc.ip) FROM {bt_tracker_connections} btc INNER JOIN {bt_tracker_users} btu on btu.uid = btc.uid WHERE btu.passkey = '%s'", $request['passkey'])); if ( $distinct_ip_connection_count > 1) { db_query("UPDATE {bt_tracker_users} SET passkey_status = 1 WHERE uid = %d", $uid); bt_error("Passkey is already in use by another peer. The passkey has been marked to be reset, please re-download all of your active torrents."); } } // Update Last user successful BitTorrent tracker activity time db_query("UPDATE {bt_tracker_users} SET last_activity = %d WHERE uid = %d", $request['current_announce'], $uid); } // Retrieve the information for the users previous request $tracker_connection = db_fetch_array(db_query("SELECT bytes_uploaded, bytes_downloaded, last_announce FROM {bt_tracker_connections} WHERE (peer_id = '%s' AND peer_key = '%s') AND fid = %d", $request['peer_id'], $request['key'], $request['fid'])); if (!$tracker_connection) { $tracker_connection['bytes_uploaded'] = 0; $tracker_connection['bytes_downloaded'] = 0; } // Update statistics if we are within a mized environment if (($_tracker_scope == 1) && array_key_exists('passkey', $request)) { // Set the statistics for the appropriate user. db_query("UPDATE {bt_tracker_users} SET bytes_uploaded = bytes_uploaded + %d, bytes_downloaded = bytes_downloaded + %d WHERE passkey = %b", ($request['uploaded'] - $tracker_connection['bytes_uploaded']), ($request['downloaded'] - $tracker_connection['bytes_downloaded']), $request['passkey']); } // Calc current upload and download speeds if (isset($tracker_connection['last_announce']) && ($time_delta = $request['current_announce'] - $tracker_connection['last_announce']) && ($time_delta > 0)) { $request['upload_speed'] = round(($request['uploaded'] - $tracker_connection['bytes_uploaded'])/$time_delta); $request['download_speed'] = round(($request['downloaded'] - $tracker_connection['bytes_downloaded'])/$time_delta); } else { $request['upload_speed'] = 0; $request['download_speed'] = 0; } // Last seed $torrent = db_fetch_object(db_query("SELECT total_size FROM {bt_torrents} WHERE fid = %d", $request['fid'])); //TODO: maybe wrong seeding condition (!) if( /*$request['downloaded'] == $torrent->total_size*/ $request['left'] == 0 ) db_query("UPDATE {bt_torrents} bt SET last_seed = %d WHERE fid = %d", $request['current_announce'], $request['fid']); //Note: When a new tracker added to already started torrent in the client (uTorrent 1.8.2). Client doesn't send 'started' event for new tracker. //Note: In some cases client can not send 'stopped' event (before next 'started' event), so we need to prevent a new start. if (!$request['event'] || ($request['event'] == 'started')) { $connection_exists = db_result(db_query("SELECT COUNT(*) > 0 FROM {bt_tracker_connections} WHERE (peer_id = '%s' AND peer_key = '%s') AND fid = %d LIMIT 1", $request['peer_id'], $request['key'], $request['fid'])); if( !$connection_exists ) { $request['event'] = 'started'; } else { unset($request['event']); } } if ($request['event'] != 'stopped' && $request['event'] != 'started') { // Update the connection statistics in the connections table db_query("UPDATE {bt_tracker_connections} SET uid = %d, ip = '%s', port = %d, bytes_uploaded = %d, bytes_downloaded = %d, bytes_left = %d, upload_speed = %d, download_speed = %d, last_announce = %d WHERE (peer_id = '%s' AND peer_key = '%s') AND fid = %d", $uid, $request['ip'], $request['port'], $request['uploaded'], $request['downloaded'], $request['left'], $request['upload_speed'], $request['download_speed'], $request['current_announce'], $request['peer_id'], $request['key'], $request['fid']); if ($request['event'] == 'completed') { // Increment the downloaded field in torrents db_query("UPDATE {bt_torrents} bt SET downloaded = downloaded + 1 WHERE fid = %d", $request['fid']); } } else if ($request['event'] == 'started') { // Add the connection to the connections table db_query("INSERT INTO {bt_tracker_connections} (uid, peer_id, peer_key, ip, port, fid, bytes_uploaded, bytes_downloaded, bytes_left, upload_speed, download_speed, last_announce) VALUES (%d, '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, %d, %d)", $uid, $request['peer_id'], $request['key'], $request['ip'], $request['port'], $request['fid'], $request['uploaded'], $request['downloaded'], $request['left'], $request['upload_speed'], $request['download_speed'], $request['current_announce']); } else if ($request['event'] == 'stopped') { // Remove the connection from the connections table db_query("DELETE FROM {bt_tracker_connections} WHERE (peer_id = '%s' AND peer_key = '%s') AND fid = %d", $request['peer_id'], $request['key'], $request['fid']); } // Build the response object // Collect peers from other (remote) trackers /* $fid = $request['fid']; //db_result(db_query("SELECT fid FROM {bt_torrents} WHERE info_hash = '%s'", $request['info_hash'])); $file = field_file_load($fid); $torrent_data = bdecode_file($file['filepath']); $announce_tier_list = torrent_get_announce_tier_list($torrent_data); $remote_request = $params; unset($remote_request['passkey']); $remote_request_query = http_build_query($remote_request, '', '&'); $remote_tracker_response_list = array(); //TODO: corrent this loop according to http://bittorrent.org/beps/bep_0012.html foreach( $announce_tier_list as $announce_tier ) foreach( $announce_tier as $announce_url ) { if( strpos($announce_url, '?') === false ) $announce_url .= '?'; else $announce_url = rtrim($announce_url, '&').'&'; $stream_context = stream_context_create(array('http' => array('user_agent' => $_SERVER['HTTP_USER_AGENT']))); $remote_response_encoded = @file_get_contents($announce_url.$remote_request_query, false, $stream_context); if( $remote_response_encoded !== false ) $remote_tracker_response_list[] = strip_excess(bdecode($remote_response_encoded)); //$remote_tracker_response_list[$announce_url] = strip_excess(bdecode($remote_response_encoded)); } */ // Retrieve the list of current connections $response['peers'] = array(); //$tracker_connection_list_result = db_query("SELECT peer_id, ip, port FROM {bt_tracker_connections} WHERE (fid = %d) AND (peer_id <> '%s') LIMIT %d", $request['fid'], $request['peer_id'], $request['numwant']); $tracker_connection_list_result = db_query("SELECT peer_id, ip, port FROM {bt_tracker_connections} WHERE (fid = %d) LIMIT %d", $request['fid'], $request['numwant']); //666 while($tracker_connection = db_fetch_array($tracker_connection_list_result)) { $response_peer = array( 'peer id' => pack('H*', $tracker_connection['peer_id']), 'ip' => bt_ip_bin2text($tracker_connection['ip'], TRUE), 'port' => $tracker_connection['port'], ); $response['peers'][] = $response_peer; } $total_tracker_response_list = (isset($remote_tracker_response_list) ? $remote_tracker_response_list : array()); $total_tracker_response_list[] = $response; //$total_tracker_response_list['-local-'] = $response; $response = torrent_merge_tracker_response_list($total_tracker_response_list); $response['interval'] = setting_get('bt_tracker', 'announce_interval'); $response['min interval'] = setting_get('bt_tracker', 'announce_min_interval'); // Pack "peers" (this is optional) $response['peers'] = torrent_pack_peers($response['peers']); // Return the response bencode_response_raw(bencode($response)); //restore_error_handler();