Codestyle

This commit is contained in:
Daniil Gentili 2023-09-01 22:06:02 +02:00
parent 26c23dc14b
commit ea741248b5
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
16 changed files with 282 additions and 1422 deletions

153
.gitignore vendored
View File

@ -1 +1,152 @@
/vendor/
MadelineProtoPhar
JSON.sh
halloween
*.raw
magnabroadcast.php
broadcast.php
docs/.jekyll-metadata
songs.php
_site
# JetBrains IDE
.idea/
*.iml
# Eclipse
.buildpath
.project
.settings
# VI
*.swp
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# emacs auto-saving files
\#*#
.#*#
vendor
*bak
token.php
*~uploading*
enc.tar.xz
a
web_data.php
web_API.log
db_connect.php
sessions
docs_md
session.mad
*.madeline
*.madeline.*
madeline.phar
madeline.phar.version
madeline.php
.env
composer.lock
b.php
telegram-cli*
src/Fuzzer.php
fuzzer.php
tests/500mb
*.save
*.save.1
*.save.*
phar7
phar5
big
*.phar
.phpunit.result.cache
.vscode/*
.vscode
custom.md
.php_cs.cache
coverage
tempConv
ponyScripts
*.madeline.*
uwu
madeline*phar
madeline*phar.version
madeline*phar.lock
e.php
.phpdoc_cache
tests/db-local.php
a.php
aa.php
aaa.php
aaaa.php
b.php
c.php
d.php
t.php
app_test.json
app.json
config.json
/Dockerfile
/docker-compose.yml
/Caddyfile
/tt.php
/changelog

24
.php-cs-fixer.dist.php Normal file
View File

@ -0,0 +1,24 @@
<?php
$config = new class extends Amp\CodeStyle\Config {
public function getRules(): array
{
return array_merge(parent::getRules(), [
'void_return' => true,
'array_indentation' => true,
'ternary_to_null_coalescing' => true,
'assign_null_coalescing_to_coalesce_equal' => true,
]);
}
};
$config->getFinder()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
->in(__DIR__ . '/examples');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;

View File

@ -7,6 +7,9 @@
"amphp/socket": "^2.2",
"webmozart/assert": "^1.11"
},
"require-dev": {
"amphp/php-cs-fixer-config": "v2.x-dev"
},
"license": "AGPLv3",
"autoload": {
"psr-4": {
@ -18,5 +21,8 @@
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
]
],
"scripts": {
"cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php -d pcre.jit=0 vendor/bin/php-cs-fixer fix -v"
}
}

1310
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use danog\Stun\Attributes\ErrorCode;
use danog\Stun\Attributes\Fingerprint;
@ -14,7 +13,8 @@ use danog\Stun\Attributes\Username;
use danog\Stun\Attributes\XorMappedAddress;
use Webmozart\Assert\Assert;
abstract class Attribute {
abstract class Attribute
{
/**
* @internal
*/
@ -24,15 +24,17 @@ abstract class Attribute {
return $resto < 0 ? $resto + \abs($b) : $resto;
}
public function write(string $transactionId): string {
public function write(string $transactionId): string
{
$data = $this->writeAttr($transactionId);
return pack('n', $this::TYPE).strlen($data).$data.str_repeat("\0", 4 - (strlen($data) % 4));
return \pack('n', $this::TYPE).\strlen($data).$data.\str_repeat("\0", 4 - (\strlen($data) % 4));
}
public static function read(BufferedReader $reader, int &$totalLength, string $transactionId, ?Cancellation $cancellation = null): ?self {
public static function read(BufferedReader $reader, int &$totalLength, string $transactionId, ?Cancellation $cancellation = null): ?self
{
$totalLength -= 4;
Assert::true($totalLength >= 0);
$r = unpack('n*', $reader->readLength(4, $cancellation));
$r = \unpack('n*', $reader->readLength(4, $cancellation));
$type = $r[1];
$length = $r[2];
$result = match ($type) {
@ -55,8 +57,9 @@ abstract class Attribute {
} else {
$reader->readLength($length, $cancellation);
}
if ($left)
if ($left) {
$reader->readLength($left, $cancellation);
}
return $result;
}

View File

@ -1,19 +1,17 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents an ERROR-CODE attribute.
*/
final class ErrorCode extends Attribute {
final class ErrorCode extends Attribute
{
public const TYPE = 0x0009;
/**
@ -22,14 +20,13 @@ final class ErrorCode extends Attribute {
public function __construct(
public readonly int $err,
public readonly string $reason
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): Attribute
{
$reader->readLength(2, $cancellation);
$class = ord($reader->readLength(1, $cancellation));
$number = ord($reader->readLength(1, $cancellation));
$class = \ord($reader->readLength(1, $cancellation));
$number = \ord($reader->readLength(1, $cancellation));
Assert::true($class >= 3);
Assert::true($class <= 6);
Assert::true($number < 100);
@ -39,6 +36,6 @@ final class ErrorCode extends Attribute {
{
$number = $this->err % 100;
$class = $this->err - $number;
return "\0\0".chr($class).chr($number).$this->reason;
return "\0\0".\chr($class).\chr($number).$this->reason;
}
}

View File

@ -1,25 +1,22 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents a FINGERPRINT attribute.
*/
final class Fingerprint extends Attribute {
final class Fingerprint extends Attribute
{
private const XOR = "\x53\x54\x55\x4e";
public const TYPE = 0x8028;
public function __construct(
public readonly string $crc
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): Attribute
{

View File

@ -1,9 +1,8 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
@ -12,36 +11,37 @@ use Webmozart\Assert\Assert;
/**
* Represents a MAPPED-ADDRESS attribute.
*/
final class MappedAddress extends Attribute {
final class MappedAddress extends Attribute
{
public const TYPE = 0x1;
public function __construct(
/**
* IP address and port
* IP address and port.
*/
public readonly InternetAddress $address,
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): self
{
Assert::true($length >= 8, "Wrong length!");
$reader->readLength(1, $cancellation);
$len = match (ord($reader->readLength(1, $cancellation))) {
$len = match (\ord($reader->readLength(1, $cancellation))) {
1 => 4,
2 => 16
};
Assert::eq($len+4, $length, "Wrong length!");
$port = unpack('n', $reader->readLength(2, $cancellation))[1];
$port = \unpack('n', $reader->readLength(2, $cancellation))[1];
$ip = $reader->readLength($len);
return new self(new InternetAddress(
inet_ntop($ip),
\inet_ntop($ip),
$port
));
}
protected function writeAttr(string $_): string {
protected function writeAttr(string $_): string
{
$addr = $this->address->getAddressBytes();
return "\0".(strlen($addr) === 4 ? 1 : 16).pack('n', $this->address->getPort()).$addr;
return "\0".(\strlen($addr) === 4 ? 1 : 16).\pack('n', $this->address->getPort()).$addr;
}
}

View File

@ -1,24 +1,21 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents a MESSAGE-INTEGRITY attribute.
*/
final class MessageIntegrity extends Attribute {
final class MessageIntegrity extends Attribute
{
public const TYPE = 0x8;
public function __construct(
public readonly string $hmac
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): Attribute
{

View File

@ -1,24 +1,20 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents a SOFTWARE attribute.
*/
final class Software extends Attribute {
final class Software extends Attribute
{
public const TYPE = 0x8022;
public function __construct(
public readonly string $software
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): Attribute
{

View File

@ -1,24 +1,20 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents a USERNAME attribute.
*/
final class Username extends Attribute {
final class Username extends Attribute
{
public const TYPE = 0x6;
public function __construct(
public readonly string $username
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): Attribute
{

View File

@ -1,54 +1,53 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun\Attributes;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Amp\Socket\InternetAddress;
use danog\Stun\Attribute;
use danog\Stun\Message;
use danog\Stun\StunClient;
use Webmozart\Assert\Assert;
/**
* Represents a XOR-MAPPED-ADDRESS attribute.
*/
final class XorMappedAddress extends Attribute {
final class XorMappedAddress extends Attribute
{
public const TYPE = 0x20;
public function __construct(
/**
* IP address and port
* IP address and port.
*/
public readonly InternetAddress $address,
)
{
) {
}
protected static function readAttr(BufferedReader $reader, string $transactionId, int $length, ?Cancellation $cancellation = null): self
{
Assert::greaterThanEq($length, 8);
$reader->readLength(1, $cancellation);
$type = ord($reader->readLength(1, $cancellation));
$port = unpack('n', $reader->readLength(2, $cancellation) ^ substr(Message::MAGIC_COOKIE, 2))[1];
$type = \ord($reader->readLength(1, $cancellation));
$port = \unpack('n', $reader->readLength(2, $cancellation) ^ \substr(Message::MAGIC_COOKIE, 2))[1];
$ip = match ($type) {
1 => $reader->readLength($len = 4, $cancellation) ^ Message::MAGIC_COOKIE,
2 => $reader->readLength($len = 16, $cancellation) ^ (Message::MAGIC_COOKIE.$transactionId)
};
Assert::eq($len+4, $length);
return new self(new InternetAddress(
inet_ntop($ip),
\inet_ntop($ip),
$port
));
}
protected function writeAttr(string $transactionId): string {
protected function writeAttr(string $transactionId): string
{
$addr = $this->address->getAddressBytes();
if (strlen($addr) === 4) {
if (\strlen($addr) === 4) {
$addr ^= Message::MAGIC_COOKIE;
} else {
$addr ^= Message::MAGIC_COOKIE.$transactionId;
}
return "\0".(strlen($addr) === 4 ? 1 : 16).(pack('n', $this->address->getPort()) ^ substr(Message::MAGIC_COOKIE, 2)).$addr;
return "\0".(\strlen($addr) === 4 ? 1 : 16).(\pack('n', $this->address->getPort()) ^ \substr(Message::MAGIC_COOKIE, 2)).$addr;
}
}

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun;
@ -7,7 +7,8 @@ use Amp\ByteStream\WritableStream;
use Amp\Cancellation;
use Webmozart\Assert\Assert;
final class Message {
final class Message
{
public const MAGIC_COOKIE = "\x21\x12\xA4\x42";
public function __construct(
@ -16,23 +17,24 @@ final class Message {
/** @var list<Attribute> */
public readonly array $attributes,
public readonly string $transactionId
)
{
Assert::true(strlen($transactionId) === 12);
) {
Assert::true(\strlen($transactionId) === 12);
}
public function write(WritableStream $writer): void {
public function write(WritableStream $writer): void
{
$attributes = '';
foreach ($this->attributes as $attr) {
$attributes .= $attr->write($this->transactionId);
}
$writer->write(
pack('nn', $this->method->value | $this->class->value, strlen($attributes)).
\pack('nn', $this->method->value | $this->class->value, \strlen($attributes)).
self::MAGIC_COOKIE.$this->transactionId.$attributes
);
}
public static function read(BufferedReader $reader, ?Cancellation $cancellation = null): self {
$type = unpack('n', $reader->readLength(2, $cancellation))[1];
$length = unpack('n', $reader->readLength(2, $cancellation))[1];
public static function read(BufferedReader $reader, ?Cancellation $cancellation = null): self
{
$type = \unpack('n', $reader->readLength(2, $cancellation))[1];
$length = \unpack('n', $reader->readLength(2, $cancellation))[1];
Assert::eq($length % 4, 0);
Assert::eq($reader->readLength(4, $cancellation), self::MAGIC_COOKIE, "Wrong magic cookie!");
$transactionId = $reader->readLength(12, $cancellation);

View File

@ -1,8 +1,9 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun;
enum MessageClass : int {
enum MessageClass: int
{
case REQUEST = 0b0000_0000_0000_0000;
case INDICATION = 0b0000_0000_0001_0000;
case SUCCESS_RESPONSE = 0b0000_0001_0000_0000;

View File

@ -1,8 +1,9 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun;
enum MessageMethod : int {
enum MessageMethod: int
{
case BINDING = 0b0000_0000_0000_0001;
public const MASK = ~MessageClass::MASK;

View File

@ -1,35 +1,35 @@
<?php
<?php declare(strict_types=1);
namespace danog\Stun;
use Amp\ByteStream\BufferedReader;
use Amp\ByteStream\ReadableBuffer;
use Amp\Socket\InternetAddress;
use Amp\Socket\Socket;
use function Amp\Socket\connect;
final class StunClient {
final class StunClient
{
private Socket $socket;
/**
* Pending outgoing requests
* Pending outgoing requests.
*
* @var array<string, Message>
*/
private array $pendingOutgoing = [];
public function __construct(
private string $endpoint
)
{
) {
$this->socket = connect($endpoint);
}
/**
* @return list<Attribute>
*/
public function bind(Attribute ...$attributes): Message {
$msg = new Message(MessageMethod::BINDING, MessageClass::REQUEST, $attributes, random_bytes(12));
public function bind(Attribute ...$attributes): Message
{
$msg = new Message(MessageMethod::BINDING, MessageClass::REQUEST, $attributes, \random_bytes(12));
$msg->write($this->socket);
$read = new ReadableBuffer($this->socket->read());
return Message::read(new BufferedReader($read));