diff --git a/includes/functions.php b/includes/functions.php index b3a892f..9f44e36 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -274,18 +274,24 @@ function purge_old_connections(): int { define('UPSTREAM_VERSION_URL', 'https://git.ny.daprogs.com/api/v1/repos/DAProgs/portspoof_concentrator/raw/version.php?ref=main'); define('UPSTREAM_VERSION_CACHE', __DIR__ . '/../upstream_version.cache'); define('UPSTREAM_VERSION_TTL', 3600); // seconds +define('UPSTREAM_VERSION_FAIL_TTL', 900); // seconds — how long to cache a failed check /** * Fetch the upstream version string from the git repo, with a 1-hour file cache. * Returns null silently on any failure so the page always loads. + * + * Failures are cached briefly too, so an unreachable git server does not + * add a cURL wait to every dashboard load (the page auto-refreshes every 30 s). */ function fetch_upstream_version(): ?string { - // Return cached value if still fresh + // Return cached value (success or failure) if still fresh if (file_exists(UPSTREAM_VERSION_CACHE)) { $cached = json_decode(file_get_contents(UPSTREAM_VERSION_CACHE), true); - if (isset($cached['version'], $cached['checked_at']) - && (time() - $cached['checked_at']) < UPSTREAM_VERSION_TTL) { - return $cached['version']; + if (isset($cached['checked_at'])) { + $ttl = isset($cached['version']) ? UPSTREAM_VERSION_TTL : UPSTREAM_VERSION_FAIL_TTL; + if ((time() - $cached['checked_at']) < $ttl) { + return $cached['version'] ?? null; + } } } @@ -293,27 +299,30 @@ function fetch_upstream_version(): ?string { curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, + CURLOPT_CONNECTTIMEOUT => 2, CURLOPT_FOLLOWLOCATION => true, ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); - if ($body === false || $code !== 200) { - return null; + if ($body !== false && $code === 200 + && preg_match("/define\s*\(\s*'APP_VERSION'\s*,\s*'([^']+)'\s*\)/", $body, $m)) { + file_put_contents( + UPSTREAM_VERSION_CACHE, + json_encode(['version' => $m[1], 'checked_at' => time()]), + LOCK_EX + ); + return $m[1]; } - if (!preg_match("/define\s*\(\s*'APP_VERSION'\s*,\s*'([^']+)'\s*\)/", $body, $m)) { - return null; - } - - $version = $m[1]; + // Cache the failure so we don't retry on every page load file_put_contents( UPSTREAM_VERSION_CACHE, - json_encode(['version' => $version, 'checked_at' => time()]), + json_encode(['version' => null, 'checked_at' => time()]), LOCK_EX ); - return $version; + return null; } /** @@ -366,8 +375,6 @@ function global_stats(): array { $total = (int)$pdo->query('SELECT COUNT(*) FROM connections')->fetchColumn(); $since = date('Y-m-d H:i:s', time() - RATE_WINDOW_SECONDS); - $recent = (int)$pdo->prepare('SELECT COUNT(*) FROM connections WHERE occurred_at >= ?') - ->execute([$since]) ? : 0; $s = $pdo->prepare('SELECT COUNT(*) FROM connections WHERE occurred_at >= ?'); $s->execute([$since]); $recent = (int)$s->fetchColumn();