Empty commit

This commit is contained in:
Git 2014-02-22 08:00:34 +00:00
parent 79651cb0aa
commit c0fee46e54
10 changed files with 281 additions and 37 deletions

View File

@ -49,6 +49,7 @@ define('SPHINX_INDEX', 'torrents');
define('TRACKER_HOST', 'localhost');
define('TRACKER_PORT', 2710);
define('TRACKER_SECRET', ''); // Must be 32 characters and match site_password in Ocelot's config.cpp
define('TRACKER_REPORTKEY', ''); // Must be 32 characters and match report_password in Ocelot's config.cpp
if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 80) {
define('SITE_URL', NONSSL_SITE_URL);

View File

@ -93,7 +93,8 @@ public function analysis($Message, $Report = '', $Time = 43200) {
'includes' => $this->get_includes(),
'cache' => $this->get_cache_keys(),
'vars' => $this->get_logged_vars(),
'perf' => $this->get_perf()
'perf' => $this->get_perf(),
'ocelot' => $this->get_ocelot_requests()
),
$Time
);
@ -304,6 +305,12 @@ public function get_logged_vars() {
return $this->LoggedVars;
}
public function get_ocelot_requests() {
if (class_exists('Tracker')) {
return Tracker::$Requests;
}
}
/* Output Formatting */
public function perf_table($Perf = false) {
@ -460,6 +467,38 @@ public function constant_table($Constants = false) {
<?
}
public function ocelot_table($OcelotRequests = false) {
if (!is_array($OcelotRequests)) {
$OcelotRequests = $this->get_ocelot_requests();
}
if (empty($OcelotRequests)) {
return;
}
?>
<table class="layout" width="100%">
<tr>
<td align="left"><strong><a href="#" onclick="$('#debug_ocelot').gtoggle(); return false;" class="brackets">View</a> <?=number_format(count($OcelotRequests))?> Ocelot requests:</strong></td>
</tr>
</table>
<table id="debug_ocelot" class="debug_table hidden" width="100%">
<? foreach ($OcelotRequests as $i => $Request) { ?>
<tr>
<td align="left" class="debug_data debug_ocelot_data">
<a href="#" onclick="$('#debug_ocelot_<?=$i?>').gtoggle(); return false"><?=display_str($Request['path'])?></a>
<pre id="debug_ocelot_<?=$i?>" class="hidden"><?=display_str($Request['response'])?></pre>
</td>
<td align="left" class="debug_info" style="width: 100px;">
<?=display_str($Request['status'])?>
</td>
<td align="left" class="debug_info debug_timing" style="width: 100px;">
<?=number_format($Request['time'], 5)?> ms
</td>
</tr>
<? } ?>
</table>
<?
}
public function cache_table($CacheKeys = false) {
$Header = 'Cache Keys';
if (!is_array($CacheKeys)) {

View File

@ -1,6 +1,11 @@
<?
// TODO: Turn this into a class with nice functions like update_user, delete_torrent, etc.
class Tracker {
const STATS_MAIN = 0;
const STATS_USER = 1;
public static $Requests = array();
/**
* Send a GET request over a socket directly to the tracker
* For example, Tracker::update_tracker('change_passkey', array('oldpasskey' => OLD_PASSKEY, 'newpasskey' => NEW_PASSKEY)) will send the request:
@ -11,62 +16,162 @@ class Tracker {
* @param boolean $ToIRC Sends a message to the channel #tracker with the GET URL.
*/
public static function update_tracker($Action, $Updates, $ToIRC = false) {
//Build request
$Get = '/update?action='.$Action;
// Build request
$Get = TRACKER_SECRET . "/update?action=$Action";
foreach ($Updates as $Key => $Value) {
$Get .= '&'.$Key.'='.$Value;
$Get .= "&$Key=$Value";
}
if ($ToIRC != false) {
send_irc('PRIVMSG #tracker :'.$Get);
$MaxAttempts = 3;
$Err = false;
if (self::send_request($Get, $MaxAttempts, $Err) === false) {
send_irc("PRIVMSG #tracker :$MaxAttempts $Err $Get");
if (G::$Cache->get_value('ocelot_error_reported') === false) {
send_irc('PRIVMSG ' . ADMIN_CHAN . " :Failed to update ocelot: $Err : $Get");
G::$Cache->cache_value('ocelot_error_reported', true, 3600);
}
return false;
}
$Path = TRACKER_SECRET.$Get;
$Header = "GET /$Path HTTP/1.0\r\n\r\n";
return true;
}
$Return = '';
/**
* Get global peer stats from the tracker
*
* @return array(0 => $Leeching, 1 => $Seeding) or false if request failed
*/
public static function global_peer_count() {
$Stats = self::get_stats(self::STATS_MAIN);
if (isset($Stats['leechers tracked']) && isset($Stats['seeders tracked'])) {
$Leechers = $Stats['leechers tracked'];
$Seeders = $Stats['seeders tracked'];
} else {
return false;
}
return array($Leechers, $Seeders);
}
/**
* Get peer stats for a user from the tracker
*
* @param string $TorrentPass The user's pass key
* @return array(0 => $Leeching, 1 => $Seeding) or false if the request failed
*/
public static function user_peer_count($TorrentPass) {
$Stats = self::get_stats(self::STATS_USER, array('key' => $TorrentPass));
if ($Stats === false) {
return false;
}
if (isset($Stats['leeching']) && isset($Stats['seeding'])) {
$Leeching = $Stats['leeching'];
$Seeding = $Stats['seeding'];
} else {
// User doesn't exist, but don't tell anyone
$Leeching = $Seeding = 0;
}
return array($Leeching, $Seeding);
}
/**
* Get whatever info the tracker has to report
*
* @return results from get_stats()
*/
public static function info() {
return self::get_stats(self::STATS_MAIN);
}
/**
* Send a stats request to the tracker and process the results
*
* @param int $Type Stats type to get
* @param array $Params Parameters required by stats type
* @return array with stats in named keys or false if the request failed
*/
private static function get_stats($Type, $Params = false) {
if (!defined('TRACKER_REPORTKEY')) {
return false;
}
$Get = TRACKER_REPORTKEY . '/report?';
if ($Type === self::STATS_MAIN) {
$Get .= 'get=stats';
} elseif ($Type === self::STATS_USER && !empty($Params['key'])) {
$Get .= "get=user&key=$Params[key]";
} else {
return false;
}
$Response = self::send_request($Get);
if ($Response === false) {
return false;
}
$Stats = array();
foreach (explode("\n", $Response) as $Stat) {
list($Val, $Key) = explode(" ", $Stat, 2);
$Stats[$Key] = $Val;
}
return $Stats;
}
/**
* Send a request to the tracker
*
* @param string $Path GET string to send to the tracker
* @param int $MaxAttempts Maximum number of failed attempts before giving up
* @param $Err Variable to use as storage for the error string if the request fails
* @return tracker response message or false if the request failed
*/
private static function send_request($Get, $MaxAttempts = 1, &$Err = false) {
$Header = "GET /$Get HTTP/1.1\r\n\r\n";
$Attempts = 0;
while ($Return != "success" && $Attempts < 3) {
// Send update
$Sleep = 0;
$Success = false;
$StartTime = microtime(true);
while (!$Success && $Attempts++ < $MaxAttempts) {
if ($Sleep) {
sleep($Sleep);
}
// Send request
$File = fsockopen(TRACKER_HOST, TRACKER_PORT, $ErrorNum, $ErrorString);
if ($File) {
if (fwrite($File, $Header) === false) {
$Attempts++;
$Err = "Failed to fwrite()";
sleep(3);
$Sleep = 3;
continue;
}
} else {
$Attempts++;
$Err = "Failed to fsockopen() - ".$ErrorNum." - ".$ErrorString;
sleep(6);
$Err = "Failed to fsockopen() - $ErrorNum - $ErrorString";
$Sleep = 6;
continue;
}
// Check for response.
$ResHeader = '';
do {
$ResHeader .= fread($File, 1);
} while (!feof($File) && !Misc::ends_with($ResHeader, "\r\n\r\n"));
$Response = '';
while ($Line = fgets($File)) {
$Response .= $Line;
while (!feof($File)) {
$Response .= fread($File, 1024);
}
$Return = chop($Response);
$Attempts++;
}
if ($Return != "success") {
send_irc("PRIVMSG #tracker :{$Attempts} {$Err} {$Get}");
if (G::$Cache->get_value('ocelot_error_reported') === false) {
send_irc("PRIVMSG ".ADMIN_CHAN." :Failed to update ocelot: ".$Err." : ".$Get);
G::$Cache->cache_value('ocelot_error_reported', true, 3600);
$DataStart = strpos($Response, "\r\n\r\n") + 4;
$DataEnd = strrpos($Response, "\n");
if ($DataEnd > $DataStart) {
$Data = substr($Response, $DataStart, $DataEnd - $DataStart);
} else {
$Data = "";
}
$Status = substr($Response, $DataEnd + 1);
if ($Status == "success") {
$Success = true;
}
}
return ($Return == "success");
$Request = array(
'path' => substr($Get, strpos($Get, '/')),
'response' => ($Success ? $Data : $Response),
'status' => ($Success ? 'ok' : 'failed'),
'time' => 1000 * (microtime(true) - $StartTime)
);
self::$Requests[] = $Request;
if ($Success) {
return $Data;
}
return false;
}
}
?>

View File

@ -46,6 +46,7 @@
$Debug->query_table();
$Debug->cache_table();
$Debug->vars_table();
$Debug->ocelot_table();
?>
</div>
<!-- End Debugging -->

View File

@ -0,0 +1,92 @@
<?
if (!check_perms('users_mod')) {
error(403);
}
if (isset($_GET['userid']) && is_number($_GET['userid'])) {
$UserHeavyInfo = Users::user_heavy_info($_GET['userid']);
if (isset($UserHeavyInfo['torrent_pass'])) {
$TorrentPass = $UserHeavyInfo['torrent_pass'];
$UserPeerStats = Tracker::user_peer_count($TorrentPass);
$UserInfo = Users::user_info($_GET['userid']);
$UserLevel = $Classes[$UserInfo['PermissionID']]['Level'];
if (!check_paranoia('leeching+', $UserInfo['Paranoia'], $UserLevel, $_GET['userid'])) {
$UserPeerStats[0] = false;
}
if (!check_paranoia('seeding+', $UserInfo['Paranoia'], $UserLevel, $_GET['userid'])) {
$UserPeerStats[1] = false;
}
} else {
$UserPeerStats = false;
}
} else {
$MainStats = Tracker::info();
}
View::show_header('Tracker info');
?>
<div class="thin">
<div class="header">
<h2>Tracker info</h2>
</div>
<div class="linkbox">
<a href="?action=<?=$_GET['action']?>" class="brackets" />Main stats</a>
</div>
<div class="sidebar">
<div class="box box2">
<div class="head"><strong>User stats</strong></div>
<div class="pad">
<form method="get" action="">
<input type="hidden" name="action" value="ocelot_info" />
<span class="label">Get stats for user</span><br />
<input type="text" name="userid" placeholder="User ID" value="<?Format::form('userid')?>" />
<input type="submit" value="Go" />
</form>
</div>
</div>
</div>
<div class="main_column">
<div class="box box2">
<div class="head"><strong>Numbers and such</strong></div>
<div class="pad">
<?
if (!empty($UserPeerStats)) {
?>
User ID: <?=$_GET['userid']?><br />
Leeching: <?=$UserPeerStats[0] === false ? "hidden" : number_format($UserPeerStats[0])?><br />
Seeding: <?=$UserPeerStats[1] === false ? "hidden" : number_format($UserPeerStats[1])?><br />
<?
} elseif (!empty($MainStats)) {
foreach ($MainStats as $Key => $Value) {
if (is_numeric($Value)) {
if (substr($Key, 0, 6) === "bytes ") {
$Value = Format::get_size($Value);
$Key = substr($Key, 6);
} else {
$Value = number_format($Value);
}
}
?>
<?="$Value $Key<br />\n"?>
<?
}
} elseif (isset($TorrentPass)) {
?>
Failed to get stats for user <?=$_GET['userid']?>
<?
} elseif (isset($_GET['userid'])) {
?>
User <?=$_GET['userid']?> doesn't exist
<?
} else {
?>
Failed to get tracker info
<?
}
?>
</div>
</div>
</div>
</div>
<?
View::show_footer();

View File

@ -186,6 +186,9 @@
case 'ocelot':
include(SERVER_ROOT.'/sections/tools/managers/ocelot.php');
break;
case 'ocelot_info':
include(SERVER_ROOT.'/sections/tools/data/ocelot_info.php');
break;
case 'official_tags':
include(SERVER_ROOT.'/sections/tools/managers/official_tags.php');
break;

View File

@ -223,6 +223,7 @@ function create_row($Title, $URL, $HasPermission = false, $Tooltip = false) {
create_row("Rerender stylesheet gallery images", "tools.php?action=rerender_gallery", check_perms("site_debug") || check_perms("users_mod"));
create_row("Schedule", "schedule.php?auth=$LoggedUser[AuthKey]", check_perms("site_debug"));
create_row("Service stats", "tools.php?action=service_stats", check_perms("site_debug"));
create_row("Tracker info", "tools.php?action=ocelot_info", check_perms("users_mod"));
create_row("Update GeoIP", "tools.php?action=update_geoip", check_perms("admin_update_geoip"));
if ($ToolsHTML) {

View File

@ -2056,6 +2056,7 @@ TODO: Make these rules apply globally and add exceptions where needed
margin: 0 0 20px 0;
}
.two_columns.pad,
#reportsv2 .pad,
#reports .pad {
padding: 10px !important;

View File

@ -1436,5 +1436,5 @@ table[width="100%"].user_options {
Consistent .box and .pad
TODO: Make these rules apply globally and add exceptions where needed
*/
#reportsv2 .pad, #reports .pad { padding: 10px !important; }
#reportsv2 .pad, #reports .pad, .two_columns.pad { padding: 10px !important; }
#reportsv2 .box, #reports .box { margin-bottom: 10px; background-color: rgb(255,255,255); border: 1px solid #aaa; color: #777; }

View File

@ -2078,6 +2078,7 @@ TODO: Make these rules apply globally and add exceptions where needed
border-radius: 4px;
}
.two_columns.pad,
#reportsv2 .pad,
#reports .pad {
padding: 10px !important;