mirror of
https://github.com/danog/stun.git
synced 2024-11-26 12:04:38 +01:00
Codestyle
This commit is contained in:
parent
26c23dc14b
commit
ea741248b5
153
.gitignore
vendored
153
.gitignore
vendored
@ -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
24
.php-cs-fixer.dist.php
Normal 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;
|
@ -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
1310
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user