the browser-facing portion of osu!

Index tsv file on download

nanaya e78b3790 740a3c63

Changed files
+98 -39
app
bin
docker
development
+2 -1
.gitignore
··· 82 82 /storage/htmlpurifier/ 83 83 /storage/paypal_auth.cache 84 84 85 - /database/ip2asn-combined.tsv 85 + /database/ip2asn.idx 86 + /database/ip2asn.tsv
+1 -1
Dockerfile.deployment
··· 52 52 COPY . . 53 53 RUN mkdir -p bootstrap/cache storage/logs storage/framework/cache storage/framework/views storage/framework/sessions public/uploads public/uploads-avatar public/uploads-replay 54 54 RUN composer dump-autoload 55 - RUN ./bin/update_ip2asn.sh 56 55 57 56 ARG APP_URL 58 57 ARG DOCS_URL 59 58 RUN yarn production 60 59 60 + RUN php artisan ip2asn:update 61 61 RUN php artisan scribe:generate 62 62 63 63 RUN rm -rf node_modules
+20
app/Console/Commands/Ip2AsnUpdate.php
··· 1 + <?php 2 + 3 + // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4 + // See the LICENCE file in the repository root for full licence text. 5 + 6 + namespace App\Console\Commands; 7 + 8 + use App\Libraries\Ip2AsnUpdater; 9 + use Illuminate\Console\Command; 10 + 11 + class Ip2AsnUpdate extends Command 12 + { 13 + protected $signature = 'ip2asn:update'; 14 + protected $description = 'Update or initialise ip2asn database'; 15 + 16 + public function handle() 17 + { 18 + (new Ip2AsnUpdater())->run(); 19 + } 20 + }
+2
app/Console/Kernel.php
··· 25 25 Commands\EsIndexScoresSetSchema::class, 26 26 Commands\EsIndexWiki::class, 27 27 28 + Commands\Ip2AsnUpdate::class, 29 + 28 30 // modding stuff 29 31 Commands\ModdingRankCommand::class, 30 32
+13 -23
app/Libraries/Ip2Asn.php
··· 11 11 12 12 class Ip2Asn 13 13 { 14 - private array $db; 15 - private $fh; 14 + private $dbFh; 15 + private string $index; 16 + private int $count; 16 17 17 18 public function __construct() 18 19 { 19 - $this->fh = fopen(database_path('ip2asn-combined.tsv'), 'r'); 20 - if ($this->fh === false) { 20 + $this->dbFh = fopen(Ip2AsnUpdater::getDbPath(), 'r'); 21 + $this->index = file_get_contents(Ip2AsnUpdater::getIndexPath()); 22 + if ($this->dbFh === false || $this->index === false) { 21 23 throw new Exception('failed opening ip2asn database'); 22 24 } 23 - $this->db = $this->parseFileForDb(); 25 + 26 + // 4 bytes per entry (int32) 27 + $this->count = strlen($this->index) / 4; 24 28 } 25 29 26 30 public function lookup(string $ip): string 27 31 { 28 32 $start = 0; 29 - $end = count($this->db) - 1; 33 + $end = $this->count - 1; 30 34 $search = inet_pton($this->prefixIPv4($ip)); 31 35 32 36 if ($search === false) { ··· 35 39 36 40 while ($start <= $end) { 37 41 $current = (int) (($start + $end) / 2); 38 - $loc = $this->db[$current]; 39 - fseek($this->fh, $loc); 40 - $row = fgets($this->fh); 42 + $loc = unpack('l', substr($this->index, $current * 4, 4))[1]; 43 + fseek($this->dbFh, $loc); 44 + $row = fgets($this->dbFh); 41 45 $data = explode("\t", $row, 4); 42 46 $compare = inet_pton($this->prefixIPv4($data[1])); 43 47 $asn = $data[2]; ··· 52 56 } 53 57 54 58 return $lastInnerSearchAsn ?? $asn; 55 - } 56 - 57 - private function parseFileForDb(): array 58 - { 59 - fseek($this->fh, 0); 60 - 61 - $ret = [ftell($this->fh)]; 62 - while (($row = fgets($this->fh)) !== false) { 63 - if ($row !== '') { 64 - $ret[] = ftell($this->fh); 65 - } 66 - } 67 - 68 - return $ret; 69 59 } 70 60 71 61 /**
+56
app/Libraries/Ip2AsnUpdater.php
··· 1 + <?php 2 + 3 + // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4 + // See the LICENCE file in the repository root for full licence text. 5 + 6 + declare(strict_types=1); 7 + 8 + namespace App\Libraries; 9 + 10 + class Ip2AsnUpdater 11 + { 12 + public static function getDbPath() 13 + { 14 + return database_path('ip2asn.tsv'); 15 + } 16 + 17 + public static function getIndexPath() 18 + { 19 + return database_path('ip2asn.idx'); 20 + } 21 + 22 + private string $tsv; 23 + 24 + public function run(): void 25 + { 26 + $dbPath = static::getDbPath(); 27 + $indexPath = static::getIndexPath(); 28 + 29 + $dbExists = file_exists($dbPath); 30 + 31 + $dbExpireTime = time() - (24 * 3600); 32 + $newDb = !$dbExists || filemtime($dbPath) < $dbExpireTime; 33 + 34 + $newIndex = !$dbExists || !file_exists($indexPath) || filemtime($dbPath) > filemtime($indexPath); 35 + if (!$newDb && !$newIndex) { 36 + return; 37 + } 38 + 39 + $tsv = $newDb 40 + ? gzdecode(file_get_contents('https://iptoasn.com/data/ip2asn-combined.tsv.gz')) 41 + : file_get_contents($dbPath); 42 + 43 + $currentLine = 0; 44 + $index = pack('l', $currentLine); 45 + while (($currentLine = strpos($tsv, "\n", $currentLine)) !== false) { 46 + $currentLine++; 47 + if (isset($tsv[$currentLine])) { 48 + $index .= pack('l', $currentLine); 49 + } 50 + } 51 + if ($newDb) { 52 + file_put_contents($dbPath, $tsv); 53 + } 54 + file_put_contents($indexPath, $index); 55 + } 56 + }
-12
bin/update_ip2asn.sh
··· 1 - #!/bin/sh 2 - 3 - set -e 4 - set -u 5 - 6 - echo 'Updating ip2asn database...' 7 - 8 - outfile="$(dirname "${0}")/../database/ip2asn-combined.tsv" 9 - curl https://iptoasn.com/data/ip2asn-combined.tsv.gz | gzip -d > "${outfile}.new" 10 - mv "${outfile}.new" "${outfile}" 11 - 12 - echo 'Finished updating ip2asn database.'
+1 -1
build.sh
··· 71 71 echo "OSU_SKIP_ASSET_BUILD set, skipping javascript asset build." 72 72 fi 73 73 74 - ./bin/update_ip2asn.sh 74 + php artisan ip2asn:update
+3 -1
docker/development/prepare.sh
··· 69 69 cp .docker/.my.cnf.example .docker/.my.cnf 70 70 fi 71 71 72 - ./bin/update_ip2asn.sh 72 + if [ ! -f database/ip2asn.tsv ]; then 73 + _run artisan ip2asn:update 74 + fi 73 75 74 76 echo "Preparation completed. Adjust .env file if needed and run 'docker compose up' followed by running migration."