ipv6 fixes

This commit is contained in:
Daniil Gentili 2020-02-28 14:14:02 +01:00
parent 883ace5d3c
commit 98e56ba62f
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
7 changed files with 48 additions and 38 deletions

View File

@ -29,9 +29,9 @@
"amphp/byte-stream": "^1", "amphp/byte-stream": "^1",
"danog/dns-over-https": "^0.2", "danog/dns-over-https": "^0.2",
"amphp/http-client-cookies": "^1", "amphp/http-client-cookies": "^1",
"amphp/uri": "^0.1",
"danog/tg-file-decoder": "^0.1", "danog/tg-file-decoder": "^0.1",
"danog/magicalserializer": "^1.0" "danog/magicalserializer": "^1.0",
"league/uri": "^6"
}, },
"require-dev": { "require-dev": {
"vlucas/phpdotenv": "^3", "vlucas/phpdotenv": "^3",

View File

@ -120,6 +120,11 @@ class DataCenter
* @var DNSConnector * @var DNSConnector
*/ */
private $dnsConnector; private $dnsConnector;
/**
* DoH connector.
*/
private Rfc6455Connector $webSocketConnnector;
public function __sleep() public function __sleep()
{ {
return ['sockets', 'curdc', 'dclist', 'settings']; return ['sockets', 'curdc', 'dclist', 'settings'];
@ -228,6 +233,7 @@ class DataCenter
$this->nonProxiedDoHClient = Magic::$altervista || Magic::$zerowebhost ? new Rfc1035StubResolver() : new Rfc8484StubResolver($nonProxiedDoHConfig); $this->nonProxiedDoHClient = Magic::$altervista || Magic::$zerowebhost ? new Rfc1035StubResolver() : new Rfc8484StubResolver($nonProxiedDoHConfig);
$this->dnsConnector = new DnsConnector(new Rfc1035StubResolver()); $this->dnsConnector = new DnsConnector(new Rfc1035StubResolver());
$this->webSocketConnnector = new Rfc6455Connector($this->HTTPClient);
} }
} }
public function dcConnect(string $dc_number, int $id = -1): \Generator public function dcConnect(string $dc_number, int $id = -1): \Generator
@ -421,6 +427,9 @@ class DataCenter
continue; continue;
} }
$address = $this->dclist[$test][$ipv6][$dc_number]['ip_address']; $address = $this->dclist[$test][$ipv6][$dc_number]['ip_address'];
if ($ipv6 === 'ipv6') {
$address = "[$address]";
}
$port = $this->dclist[$test][$ipv6][$dc_number]['port']; $port = $this->dclist[$test][$ipv6][$dc_number]['port'];
foreach (\array_unique([$port, 443, 80, 88, 5222]) as $port) { foreach (\array_unique([$port, 443, 80, 88, 5222]) as $port) {
$stream = \end($combo)[0]; $stream = \end($combo)[0];
@ -459,7 +468,7 @@ class DataCenter
$stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector; $stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector;
} }
if (\in_array($stream[0], [WsStream::class, WssStream::class]) && $stream[1] === []) { if (\in_array($stream[0], [WsStream::class, WssStream::class]) && $stream[1] === []) {
$stream[1] = new Rfc6455Connector($this->HTTPClient); $stream[1] = $this->webSocketConnnector;
} }
$ctx->addStream(...$stream); $ctx->addStream(...$stream);
} }

View File

@ -438,7 +438,7 @@ class DataCenterConnection implements JsonSerializable
* *
* @return void * @return void
*/ */
public function disconnect() public function disconnect(): void
{ {
$this->connectionsDeferred = new Deferred(); $this->connectionsDeferred = new Deferred();
$this->connectionsPromise = $this->connectionsDeferred->promise(); $this->connectionsPromise = $this->connectionsDeferred->promise();

View File

@ -21,10 +21,11 @@ namespace danog\MadelineProto\Stream;
use Amp\CancellationToken; use Amp\CancellationToken;
use Amp\Socket\ConnectContext; use Amp\Socket\ConnectContext;
use Amp\Uri\Uri;
use danog\MadelineProto\Exception; use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream; use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Stream\Transport\DefaultStream; use danog\MadelineProto\Stream\Transport\DefaultStream;
use League\Uri\Http;
use Psr\Http\Message\UriInterface;
/** /**
* Connection context class. * Connection context class.
@ -63,7 +64,7 @@ class ConnectionContext
/** /**
* The connection URI. * The connection URI.
* *
* @var \Amp\Uri\Uri * @var UriInterface
*/ */
private $uri; private $uri;
/** /**
@ -138,13 +139,13 @@ class ConnectionContext
/** /**
* Set the connection URI. * Set the connection URI.
* *
* @param string|\Amp\Uri\Uri $uri * @param string|UriInterface $uri
* *
* @return self * @return self
*/ */
public function setUri($uri): self public function setUri($uri): self
{ {
$this->uri = $uri instanceof Uri ? $uri : new Uri($uri); $this->uri = $uri instanceof UriInterface ? $uri : Http::createFromString($uri);
return $this; return $this;
} }
/** /**
@ -159,9 +160,9 @@ class ConnectionContext
/** /**
* Get the URI. * Get the URI.
* *
* @return \Amp\Uri\Uri * @return UriInterface
*/ */
public function getUri(): Uri public function getUri(): UriInterface
{ {
return $this->uri; return $this->uri;
} }
@ -463,7 +464,7 @@ class ConnectionContext
} }
$string .= \preg_replace('/.*\\\\/', '', $stream[0]); $string .= \preg_replace('/.*\\\\/', '', $stream[0]);
if ($stream[1] && $stream[0] !== DefaultStream::getName()) { if ($stream[1] && $stream[0] !== DefaultStream::getName()) {
$string .= ' (' . \json_encode($stream[1]) . ')'; $string .= ' ('.\json_encode($stream[1]).')';
} }
} }
return $string; return $string;

View File

@ -27,6 +27,7 @@ use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext; use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface; use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface; use danog\MadelineProto\Stream\RawStreamInterface;
use Psr\Http\Message\UriInterface;
/** /**
* HTTP stream wrapper. * HTTP stream wrapper.
@ -42,10 +43,8 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
private $header = ''; private $header = '';
/** /**
* URI of the HTTP API. * URI of the HTTP API.
*
* @var \Amp\Uri\Uri
*/ */
private $uri; private UriInterface $uri;
/** /**
* Connect to stream. * Connect to stream.
* *

View File

@ -68,8 +68,10 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface
throw new \danog\MadelineProto\Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"'); throw new \danog\MadelineProto\Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"');
} }
$this->dc = $ctx->getIntDc(); $this->dc = $ctx->getIntDc();
$handshake = new Handshake(\str_replace('tcp://', $ctx->isSecure() ? 'wss://' : 'ws://', $ctx->getStringUri())); $uri = $ctx->getStringUri();
$this->stream = (yield ($this->connector ?? connector())->connect($handshake, $ctx->getCancellationToken())); $uri = \str_replace('tcp://', $ctx->isSecure() ? 'wss://' : 'ws://', $uri);
$handshake = new Handshake($uri);
$this->stream = yield ($this->connector ?? connector())->connect($handshake, $ctx->getCancellationToken());
if (\strlen($header)) { if (\strlen($header)) {
yield $this->write($header); yield $this->write($header);
} }

View File

@ -20,15 +20,14 @@ final class DataCenterTest extends TestCase
* @param string $protocol Protocol name * @param string $protocol Protocol name
* @param boolean $test_mode Test mode * @param boolean $test_mode Test mode
* @param boolean $ipv6 IPv6 * @param boolean $ipv6 IPv6
* @param boolean $doh DNS over HTTPS?
* *
* @dataProvider protocolProvider * @dataProvider protocolProvider
* *
* @return void * @return void
*/ */
public function testCanUseProtocol(string $transport, bool $obfuscated, string $protocol, bool $test_mode, bool $ipv6, bool $doh): void public function testCanUseProtocol(string $transport, bool $obfuscated, string $protocol, bool $test_mode, bool $ipv6): void
{ {
$settings = MTProto::getSettings( $settings = MTProto::parseSettings(
[ [
'connection_settings' => [ 'connection_settings' => [
'all' => [ 'all' => [
@ -36,7 +35,8 @@ final class DataCenterTest extends TestCase
'test_mode' => $test_mode, 'test_mode' => $test_mode,
'protocol' => $protocol, 'protocol' => $protocol,
'obfuscated' => $obfuscated, 'obfuscated' => $obfuscated,
'transport' => $transport 'transport' => $transport,
'do_not_retry' => true
], ],
], ],
'logger' => [ 'logger' => [
@ -73,45 +73,44 @@ final class DataCenterTest extends TestCase
); );
$API->datacenter = $datacenter; $API->datacenter = $datacenter;
$API->getLogger()->logger("Testing protocol $protocol using transport $transport, ".($obfuscated ? 'obfuscated ' : 'not obfuscated ').($test_mode ? 'test DC ' : 'main DC ').($ipv6 ? 'IPv6 ' : 'IPv4 ').($doh ? "DNS over HTTPS" : "DNS")); $API->getLogger()->logger("Testing protocol $protocol using transport $transport, ".($obfuscated ? 'obfuscated ' : 'not obfuscated ').($test_mode ? 'test DC ' : 'main DC ').($ipv6 ? 'IPv6 ' : 'IPv4 '));
\sleep(1); \sleep(1);
try { try {
Tools::wait($datacenter->dcConnect(2)); Tools::wait($datacenter->dcConnect(2));
} catch (\Throwable $e) {
if (!$test_mode) {
throw $e;
}
} finally { } finally {
Tools::wait($datacenter->getDataCenterConnection(2)->disconnect()); $datacenter->getDataCenterConnection(2)->disconnect();
} }
$this->assertTrue(true); $this->assertTrue(true);
} }
public function protocolProvider(): \Generator public function protocolProvider(): \Generator
{ {
return yield;
$ipv6Pair = [false]; $ipv6Pair = [false];
if (@\file_get_contents('https://ipv6.google.com')) { if (@\file_get_contents('https://ipv6.google.com')) {
$ipv6Pair []= true; $ipv6Pair []= true;
} }
foreach ([false, true] as $test_mode) { foreach ([false, true] as $test_mode) {
foreach ([false, true] as $doh) { foreach ($ipv6Pair as $ipv6) {
foreach ($ipv6Pair as $ipv6) { foreach (['tcp', 'ws', 'wss'] as $transport) {
foreach (['tcp', 'ws', 'wss'] as $transport) { foreach ([true, false] as $obfuscated) {
foreach ([true, false] as $obfuscated) { if ($transport !== 'tcp' && !$obfuscated) {
if ($transport !== 'tcp' && !$obfuscated) { continue;
}
foreach (['abridged', 'intermediate', 'intermediate_padded', 'full'] as $protocol) {
if ($protocol === 'full' && $obfuscated) {
continue; continue;
} }
foreach (['abridged', 'intermediate', 'intermediate_padded', 'full'] as $protocol) { yield [$transport, $obfuscated, $protocol, $test_mode, $ipv6];
if ($protocol === 'full' && $obfuscated) {
continue;
}
yield [$transport, $obfuscated, $protocol, $test_mode, $ipv6, $doh];
}
} }
} }
yield ['tcp', false, 'http', $test_mode, $ipv6, true];
yield ['tcp', false, 'https', $test_mode, $ipv6, true];
yield ['tcp', false, 'http', $test_mode, $ipv6, false];
yield ['tcp', false, 'https', $test_mode, $ipv6, false];
} }
yield ['tcp', false, 'http', $test_mode, $ipv6];
yield ['tcp', false, 'https', $test_mode, $ipv6];
} }
} }
} }