Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Debrigode committed Jan 26, 2024
1 parent e81b652 commit fdc24a0
Show file tree
Hide file tree
Showing 21 changed files with 438 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ APP_ENV=prod
APP_SECRET=644192852c93fabc1bb219ad6458fe25

CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'

PEERINGDB_HOST='https://peeringdb.com'
PEERINGDB_URI='/api/'
1 change: 1 addition & 0 deletions asstats.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ config:
daystatsfile: '/home/nidebr/data/DEV/asstats/stats/asstats_day.txt'
knownlinksfile: '/home/nidebr/data/DEV/asstats/conf/knownlinks'
asinfofile: 'ressources/asinfo.db'
myasn: 34863
graph:
showv6: true
outispositive: false
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"symfony/flex": "^2",
"symfony/form": "7.0.*",
"symfony/framework-bundle": "7.0.*",
"symfony/http-client": "7.0.*",
"symfony/process": "7.0.*",
"symfony/property-access": "7.0.*",
"symfony/runtime": "7.0.*",
Expand Down
5 changes: 5 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ services:
App\Application\ConfigApplication:
arguments:
- '%kernel.environment%'

## peeringdb client
App\Client\PeeringDbClient:
$host: '%env(PEERINGDB_HOST)%'
$uri: '%env(PEERINGDB_URI)%'
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ parameters:

ignoreErrors:
- '#Only booleans are allowed#'
- '#Cannot cast mixed to int.#'
13 changes: 13 additions & 0 deletions src/Application/ConfigApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ public static function getAsStatsConfigTop(): int
return self::getAsStatsConfig()['top'];
}

public static function getAsStatsConfigMyAsn(): ?int
{
if (false === \array_key_exists('myasn', self::getAsStatsConfig())) {
return null;
}

if (!self::getAsStatsConfig()['myasn']) {
return null;
}

return self::getAsStatsConfig()['myasn'];
}

/**
* @throws ConfigErrorException
*/
Expand Down
64 changes: 64 additions & 0 deletions src/Client/PeeringDbClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace App\Client;

use App\Util\EndWithFunction;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class PeeringDbClient extends AbstractController
{
public function __construct(
readonly string $host,
readonly string $uri,
private HttpClientInterface $client,
) {
if (!EndWithFunction::endsWith($uri, '/')) {
$uri = \sprintf('%s/', $uri);
}

$this->client = $client->withOptions([
'base_uri' => \sprintf('%s%s', $host, $uri),
'verify_host' => false,
'verify_peer' => false,
'timeout' => 30,
'max_duration' => 30,
]);
}

/**
* @throws TransportExceptionInterface
*/
public function get(string $url): array
{
$response = $this->client->request('GET', $url, [
'headers' => [
'Content-Type' => 'application/json',
],
]);

try {
return [
'status_code' => $response->getStatusCode(),
'response' => $response->toArray(),
];
} catch (ClientExceptionInterface|TransportExceptionInterface|DecodingExceptionInterface|ServerExceptionInterface|RedirectionExceptionInterface $e) {
if (429 === $e->getCode()) {
$this->addFlash('warning', 'Request was throttled by peeringdb.com API server.');
}

return [
'status_code' => $e->getCode(),
'message' => $e->getMessage(),
'response' => [],
];
}
}
}
87 changes: 87 additions & 0 deletions src/Controller/IXStatsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace App\Controller;

use App\Application\ConfigApplication;
use App\Exception\ConfigErrorException;
use App\Exception\DbErrorException;
use App\Form\SelectMyIXForm;
use App\Repository\GetAsDataRepository;
use App\Repository\KnowlinksRepository;
use App\Repository\PeeringDBRepository;
use App\Util\Annotation\Menu;
use Doctrine\DBAL\Exception;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

#[Route(
path: '/ix',
)]
#[Menu('view_ix')]
class IXStatsController extends BaseController
{
protected array $data = [];

/**
* @throws ConfigErrorException
* @throws DbErrorException
* @throws Exception
*/
#[Route(
path: '/my-ix',
name: 'my_ix',
methods: ['GET|POST'],
)]
public function history(
Request $request,
PeeringDBRepository $peeringDBRepository,
GetAsDataRepository $asDataRepository,
ConfigApplication $Config,
): Response {
$this->base_data['content_wrapper']['titre'] = 'My IX Stats';

$form = $this->createForm(SelectMyIXForm::class);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$ixInfo = $peeringDBRepository->getIXInfo((int) $form->get('myix')->getData());

$this->base_data['content_wrapper']['titre'] = \sprintf(
'Top %s (%s)',
$this->base_data['top'],
'24 hours'
);

$this->base_data['content_wrapper']['small'] = $ixInfo['name'];
$this->data['data'] = $asDataRepository::get(
$this->base_data['top'],
'',
[],
$peeringDBRepository->getIXMembers((int) $form->get('myix')->getData()),
);

$this->data['start'] = time() - 24 * 3600;
$this->data['end'] = time();
$this->data['graph_size'] = [
'width' => $Config::getAsStatsConfigGraph()['top_graph_width'],
'height' => $Config::getAsStatsConfigGraph()['top_graph_height'],
];
$this->data['selectedLinks'] = [];

return $this->render('pages/ix/my_ix/show.html.twig', [
'base_data' => $this->base_data,
'data' => $this->data,
'knownlinks' => KnowlinksRepository::get(),
'form' => $form->createView(),
]);
}

return $this->render('pages/ix/my_ix/index.html.twig', [
'base_data' => $this->base_data,
'form' => $form->createView(),
]);
}
}
2 changes: 1 addition & 1 deletion src/Controller/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function index(
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$this->data['data'] = $asDataRepository::get($this->base_data['top'], null, (array) $form->getData());
$this->data['data'] = $asDataRepository::get($this->base_data['top'], '', (array) $form->getData());
$this->data['selectedLinks'] = KnowlinksRepository::select((array) $form->getData());
} else {
$this->data['data'] = $asDataRepository::get($this->base_data['top']);
Expand Down
50 changes: 50 additions & 0 deletions src/Form/SelectMyIXForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Form;

use App\Application\ConfigApplication;
use App\Client\PeeringDbClient;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SelectMyIXForm extends AbstractType
{
public function __construct(private PeeringDbClient $peeringDbClient)
{
}

/**
* @param array<string, mixed> $options
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$peering_data = $this->peeringDbClient->get(\sprintf('netixlan?asn=%s', ConfigApplication::getAsStatsConfigMyAsn()));

$data = [];
if (200 === $peering_data['status_code']) {
foreach ($peering_data['response']['data'] as $myix) {
$data[$myix['name']] = $myix['ix_id'];
}
}

ksort($data);

$builder
->add('myix', ChoiceType::class, [
'label' => false,
'choices' => $data,
'choice_translation_domain' => false,
]);
}

public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'csrf_protection' => false,
]);
}
}
2 changes: 1 addition & 1 deletion src/Repository/DbAsStatsRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function getASStatsTop(int $ntop, array $selected_links, array $list_asn
->setMaxResults($ntop)
->fetchAllAssociative();
}
} catch (Exception) {
} catch (Exception $e) {
throw new DbErrorException(\sprintf('Problem with stats files %s', $this->dbname));
}

Expand Down
9 changes: 5 additions & 4 deletions src/Repository/GetAsDataRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ class GetAsDataRepository
*/
public static function get(
int $top,
?string $topInterval = null,
array $selectedLinks = []
string $topInterval = '',
array $selectedLinks = [],
array $listAsn = [],
): array {
if (0 === $top) {
return [];
}

$return = [];

if ($topInterval) {
if ('' !== $topInterval && '0' !== $topInterval) {
$dbName = ConfigApplication::getAsStatsConfigTopInterval()[$topInterval]['statsfile'];
} else {
$dbName = ConfigApplication::getAsStatsConfigDayStatsFile();
Expand All @@ -36,7 +37,7 @@ public static function get(
$data = new DbAsStatsRepository($dbName);
$asInfoRepository = new DbAsInfoRepository();

foreach ($data->getASStatsTop($top, KnowlinksRepository::select($selectedLinks)) as $as => $nbytes) {
foreach ($data->getASStatsTop($top, KnowlinksRepository::select($selectedLinks), $listAsn) as $as => $nbytes) {
$return['asinfo'][$as]['info'] = $asInfoRepository->getAsInfo($as);

$return['asinfo'][$as]['v4'] = [
Expand Down
44 changes: 44 additions & 0 deletions src/Repository/PeeringDBRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace App\Repository;

use App\Client\PeeringDbClient;

class PeeringDBRepository
{
private PeeringDbClient $peeringDbClient;

public function __construct(PeeringDbClient $peeringDbClient)
{
$this->peeringDbClient = $peeringDbClient;
}

public function getIXMembers(int $ix_id): array
{
$data = $this->peeringDbClient->get(\sprintf('net?ix_id=%s', $ix_id));

if (200 !== $data['status_code']) {
return [];
}

$asn = [];
foreach ($data['response']['data'] as $list) {
$asn[] = $list['asn'];
}

return $asn;
}

public function getIXInfo(int $ix_id): array
{
$data = $this->peeringDbClient->get(\sprintf('ix?id=%s', $ix_id));

if (200 !== $data['status_code']) {
return [];
}

return $data['response']['data'][0];
}
}
8 changes: 7 additions & 1 deletion src/Twig/ConfigApplicationExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ public function getFunctions(): array
{
return [
new TwigFunction('configapplication_graph', [$this, 'getConfigGraph']),
new TwigFunction('configapplication_myasn', [$this, 'getConfigMyAsn']),
];
}

public function getConfigGraph(string $key): mixed
{
if ($key === '' || $key === '0') {
if ('' === $key || '0' === $key) {
return '';
}

Expand All @@ -38,4 +39,9 @@ public function getConfigGraph(string $key): mixed

return $this->configApplication::getAsStatsConfigGraph()[$key];
}

public function getConfigMyAsn(): ?int
{
return $this->configApplication::getAsStatsConfigMyAsn();
}
}
16 changes: 16 additions & 0 deletions src/Util/EndWithFunction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace App\Util;

class EndWithFunction
{
public static function endsWith(string $FullStr, string $needle): bool
{
$StrLen = strlen($needle);
$FullStrEnd = substr($FullStr, strlen($FullStr) - $StrLen);

return $FullStrEnd === $needle;
}
}
Loading

0 comments on commit fdc24a0

Please sign in to comment.