diff --git a/README.md b/README.md index bb4e5f1..bfd0cc3 100644 --- a/README.md +++ b/README.md @@ -23,24 +23,19 @@ handle multiple connections without blocking. * [ConnectionInterface](#connectioninterface) * [getRemoteAddress()](#getremoteaddress) * [getLocalAddress()](#getlocaladdress) - * [Plaintext TCP/IP connections](#plaintext-tcpip-connections) - * [DNS resolution](#dns-resolution) - * [Secure TLS connections](#secure-tls-connections) - * [Connection timeout](#connection-timeouts) - * [Unix domain sockets](#unix-domain-sockets) + * [Connector](#connector) +* [Advanced Usage](#advanced-usage) + * [TcpConnector](#tcpconnector) + * [DnsConnector](#dnsconnector) + * [SecureConnector](#secureconnector) + * [TimeoutConnector](#timeoutconnector) + * [UnixConnector](#unixconnector) * [Install](#install) * [Tests](#tests) * [License](#license) ## Usage -In order to use this project, you'll need the following react boilerplate code -to initialize the main loop. - -```php -$loop = React\EventLoop\Factory::create(); -``` - ### ConnectorInterface The `ConnectorInterface` is responsible for providing an interface for @@ -187,7 +182,228 @@ If your system has multiple interfaces (e.g. a WAN and a LAN interface), you can use this method to find out which interface was actually used for this connection. -### Plaintext TCP/IP connections +### Connector + +The `Connector` class is the main class in this package that implements the +[`ConnectorInterface`](#connectorinterface) and allows you to create streaming connections. + +You can use this connector to create any kind of streaming connections, such +as plaintext TCP/IP, secure TLS or local Unix connection streams. + +It binds to the main event loop and can be used like this: + +```php +$loop = React\EventLoop\Factory::create(); +$connector = new Connector($loop); + +$connector->connect($uri)->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); + +$loop->run(); +``` + +In order to create a plaintext TCP/IP connection, you can simply pass a host +and port combination like this: + +```php +$connector->connect('www.google.com:80')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +> If you do no specify a URI scheme in the destination URI, it will assume + `tcp://` as a default and establish a plaintext TCP/IP connection. + Note that TCP/IP connections require a host and port part in the destination + URI like above, all other URI components are optional. + +In order to create a secure TLS connection, you can use the `tls://` URI scheme +like this: + +```php +$connector->connect('tls://www.google.com:443')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +In order to create a local Unix domain socket connection, you can use the +`unix://` URI scheme like this: + +```php +$connector->connect('unix:///tmp/demo.sock')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +Under the hood, the `Connector` is implemented as a *higher-level facade* +for the lower-level connectors implemented in this package. This means it +also shares all of their features and implementation details. +If you want to typehint in your higher-level protocol implementation, you SHOULD +use the generic [`ConnectorInterface`](#connectorinterface) instead. + +In particular, the `Connector` class uses Google's public DNS server `8.8.8.8` +to resolve all hostnames into underlying IP addresses by default. +This implies that it also ignores your `hosts` file and `resolve.conf`, which +means you won't be able to connect to `localhost` and other non-public +hostnames by default. +If you want to use a custom DNS server (such as a local DNS relay), you can set +up the `Connector` like this: + +```php +$connector = new Connector($loop, array( + 'dns' => '127.0.1.1' +)); + +$connector->connect('localhost:80')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +If you do not want to use a DNS resolver at all and want to connect to IP +addresses only, you can also set up your `Connector` like this: + +```php +$connector = new Connector($loop, array( + 'dns' => false +)); + +$connector->connect('127.0.0.1:80')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +Advanced: If you need a custom DNS `Resolver` instance, you can also set up +your `Connector` like this: + +```php +$dnsResolverFactory = new React\Dns\Resolver\Factory(); +$resolver = $dnsResolverFactory->createCached('127.0.1.1', $loop); + +$connector = new Connector($loop, array( + 'dns' => $resolver +)); + +$connector->connect('localhost:80')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +By default, the `tcp://` and `tls://` URI schemes will use timeout value that +repects your `default_socket_timeout` ini setting (which defaults to 60s). +If you want a custom timeout value, you can simply pass this like this: + +```php +$connector = new Connector($loop, array( + 'timeout' => 10.0 +)); +``` + +Similarly, if you do not want to apply a timeout at all and let the operating +system handle this, you can pass a boolean flag like this: + +```php +$connector = new Connector($loop, array( + 'timeout' => false +)); +``` + +By default, the `Connector` supports the `tcp://`, `tls://` and `unix://` +URI schemes. If you want to explicitly prohibit any of these, you can simply +pass boolean flags like this: + +```php +// only allow secure TLS connections +$connector = new Connector($loop, array( + 'tcp' => false, + 'tls' => true, + 'unix' => false, +)); + +$connector->connect('tls://google.com:443')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +The `tcp://` and `tls://` also accept additional context options passed to +the underlying connectors. +If you want to explicitly pass additional context options, you can simply +pass arrays of context options like this: + +```php +// allow insecure TLS connections +$connector = new Connector($loop, array( + 'tcp' => array( + 'bindto' => '192.168.0.1:0' + ), + 'tls' => array( + 'verify_peer' => false, + 'verify_peer_name' => false + ), +)); + +$connector->connect('tls://localhost:443')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +> For more details about context options, please refer to the PHP documentation + about [socket context options](http://php.net/manual/en/context.socket.php) + and [SSL context options](http://php.net/manual/en/context.ssl.php). + +Advanced: By default, the `Connector` supports the `tcp://`, `tls://` and +`unix://` URI schemes. +For this, it sets up the required connector classes automatically. +If you want to explicitly pass custom connectors for any of these, you can simply +pass an instance implementing the `ConnectorInterface` like this: + +```php +$dnsResolverFactory = new React\Dns\Resolver\Factory(); +$resolver = $dnsResolverFactory->createCached('127.0.1.1', $loop); +$tcp = new DnsConnector(new TcpConnector($loop), $resolver); + +$tls = new SecureConnector($tcp, $loop); + +$unix = new UnixConnector($loop); + +$connector = new Connector($loop, array( + 'tcp' => $tcp, + 'tls' => $tls, + 'unix' => $unix, + + 'dns' => false, + 'timeout' => false, +)); + +$connector->connect('google.com:80')->then(function (ConnectionInterface $connection) { + $connection->write('...'); + $connection->end(); +}); +``` + +> Internally, the `tcp://` connector will always be wrapped by the DNS resolver, + unless you disable DNS like in the above example. In this case, the `tcp://` + connector receives the actual hostname instead of only the resolved IP address + and is thus responsible for performing the lookup. + Internally, the automatically created `tls://` connector will always wrap the + underlying `tcp://` connector for establishing the underlying plaintext + TCP/IP connection before enabling secure TLS mode. If you want to use a custom + underlying `tcp://` connector for secure TLS connections only, you may + explicitly pass a `tls://` connector like above instead. + Internally, the `tcp://` and `tls://` connectors will always be wrapped by + `TimeoutConnector`, unless you disable timeouts like in the above example. + +## Advanced Usage + +### TcpConnector The `React\SocketClient\TcpConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to create plaintext @@ -246,7 +462,7 @@ be used to set up the TLS peer name. This is used by the `SecureConnector` and `DnsConnector` to verify the peer name and can also be used if you want a custom TLS peer name. -### DNS resolution +### DnsConnector The `DnsConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to create plaintext @@ -260,7 +476,7 @@ Make sure to set up your DNS resolver and underlying TCP connector like this: ```php $dnsResolverFactory = new React\Dns\Resolver\Factory(); -$dns = $dnsResolverFactory->connectCached('8.8.8.8', $loop); +$dns = $dnsResolverFactory->createCached('8.8.8.8', $loop); $dnsConnector = new React\SocketClient\DnsConnector($tcpConnector, $dns); @@ -306,7 +522,7 @@ hostname and is used by the `TcpConnector` to set up the TLS peer name. If a `hostname` is given explicitly, this query parameter will not be modified, which can be useful if you want a custom TLS peer name. -### Secure TLS connections +### SecureConnector The `SecureConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to create secure @@ -360,7 +576,7 @@ Failing to do so may result in a TLS peer name mismatch error or some hard to trace race conditions, because all stream resources will use a single, shared *default context* resource otherwise. -### Connection timeouts +### TimeoutConnector The `TimeoutConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to add timeout @@ -391,7 +607,7 @@ $promise->cancel(); Calling `cancel()` on a pending promise will cancel the underlying connection attempt, abort the timer and reject the resulting promise. -### Unix domain sockets +### UnixConnector The `UnixConnector` class implements the [`ConnectorInterface`](#connectorinterface) and allows you to connect to diff --git a/examples/01-http.php b/examples/01-http.php index 9b06cc2..95519c9 100644 --- a/examples/01-http.php +++ b/examples/01-http.php @@ -1,27 +1,17 @@ create('8.8.8.8', $loop); - -$tcp = new TcpConnector($loop); -$dns = new DnsConnector($tcp, $resolver); - -// time out connection attempt in 3.0s -$dns = new TimeoutConnector($dns, 3.0, $loop); - -$target = isset($argv[1]) ? $argv[1] : 'www.google.com:80'; - -$dns->connect($target)->then(function (ConnectionInterface $connection) use ($target) { +$connector->connect($target)->then(function (ConnectionInterface $connection) use ($target) { $connection->on('data', function ($data) { echo $data; }); diff --git a/examples/02-https.php b/examples/02-https.php index 9672192..b1780de 100644 --- a/examples/02-https.php +++ b/examples/02-https.php @@ -1,29 +1,17 @@ create('8.8.8.8', $loop); - -$tcp = new TcpConnector($loop); -$dns = new DnsConnector($tcp, $resolver); -$tls = new SecureConnector($dns, $loop); - -// time out connection attempt in 3.0s -$tls = new TimeoutConnector($tls, 3.0, $loop); - -$target = isset($argv[1]) ? $argv[1] : 'www.google.com:443'; - -$tls->connect($target)->then(function (ConnectionInterface $connection) use ($target) { +$connector->connect('tls://' . $target)->then(function (ConnectionInterface $connection) use ($target) { $connection->on('data', function ($data) { echo $data; }); diff --git a/examples/03-netcat.php b/examples/03-netcat.php index e0c633c..42c1234 100644 --- a/examples/03-netcat.php +++ b/examples/03-netcat.php @@ -1,10 +1,9 @@ create('8.8.8.8', $loop); - -$tcp = new TcpConnector($loop); -$dns = new DnsConnector($tcp, $resolver); - -// time out connection attempt in 3.0s -$dns = new TimeoutConnector($dns, 3.0, $loop); +$connector = new Connector($loop); $stdin = new Stream(STDIN, $loop); $stdin->pause(); @@ -33,7 +24,7 @@ $stderr->write('Connecting' . PHP_EOL); -$dns->connect($argv[1])->then(function (ConnectionInterface $connection) use ($stdin, $stdout, $stderr) { +$connector->connect($argv[1])->then(function (ConnectionInterface $connection) use ($stdin, $stdout, $stderr) { // pipe everything from STDIN into connection $stdin->resume(); $stdin->pipe($connection); diff --git a/examples/04-web.php b/examples/04-web.php new file mode 100644 index 0000000..faaf5ed --- /dev/null +++ b/examples/04-web.php @@ -0,0 +1,48 @@ +' . PHP_EOL); + exit(1); +} + +$loop = Factory::create(); +$connector = new Connector($loop); + +if (!isset($parts['port'])) { + $parts['port'] = $parts['scheme'] === 'https' ? 443 : 80; +} + +$host = $parts['host']; +if (($parts['scheme'] === 'http' && $parts['port'] !== 80) || ($parts['scheme'] === 'https' && $parts['port'] !== 443)) { + $host .= ':' . $parts['port']; +} +$target = ($parts['scheme'] === 'https' ? 'tls' : 'tcp') . '://' . $parts['host'] . ':' . $parts['port']; +$resource = isset($parts['path']) ? $parts['path'] : '/'; +if (isset($parts['query'])) { + $resource .= '?' . $parts['query']; +} + +$stdout = new Stream(STDOUT, $loop); +$stdout->pause(); + +$connector->connect($target)->then(function (ConnectionInterface $connection) use ($resource, $host, $stdout) { + $connection->pipe($stdout); + + $connection->write("GET $resource HTTP/1.0\r\nHost: $host\r\n\r\n"); +}, 'printf'); + +$loop->run(); diff --git a/src/Connector.php b/src/Connector.php index 4a07c81..7a6d81d 100644 --- a/src/Connector.php +++ b/src/Connector.php @@ -4,28 +4,124 @@ use React\EventLoop\LoopInterface; use React\Dns\Resolver\Resolver; +use React\Dns\Resolver\Factory; +use React\Promise; +use RuntimeException; /** - * Legacy Connector + * The `Connector` class is the main class in this package that implements the + * `ConnectorInterface` and allows you to create streaming connections. * - * This class is not to be confused with the ConnectorInterface and should not - * be used as a typehint. + * You can use this connector to create any kind of streaming connections, such + * as plaintext TCP/IP, secure TLS or local Unix connection streams. + * + * Under the hood, the `Connector` is implemented as a *higher-level facade* + * or the lower-level connectors implemented in this package. This means it + * also shares all of their features and implementation details. + * If you want to typehint in your higher-level protocol implementation, you SHOULD + * use the generic [`ConnectorInterface`](#connectorinterface) instead. * - * @deprecated Exists for BC only, consider using the newer DnsConnector instead - * @see DnsConnector for the newer replacement * @see ConnectorInterface for the base interface */ final class Connector implements ConnectorInterface { - private $connector; + private $connectors = array(); - public function __construct(LoopInterface $loop, Resolver $resolver) + public function __construct(LoopInterface $loop, array $options = array()) { - $this->connector = new DnsConnector(new TcpConnector($loop), $resolver); + // apply default options if not explicitly given + $options += array( + 'tcp' => true, + 'tls' => true, + 'unix' => true, + + 'dns' => true, + 'timeout' => true, + ); + + if ($options['timeout'] === true) { + $options['timeout'] = (float)ini_get("default_socket_timeout"); + } + + if ($options['tcp'] instanceof ConnectorInterface) { + $tcp = $options['tcp']; + } else { + $tcp = new TcpConnector( + $loop, + is_array($options['tcp']) ? $options['tcp'] : array() + ); + } + + if ($options['dns'] !== false) { + if ($options['dns'] instanceof Resolver) { + $resolver = $options['dns']; + } else { + $factory = new Factory(); + $resolver = $factory->create( + $options['dns'] === true ? '8.8.8.8' : $options['dns'], + $loop + ); + } + + $tcp = new DnsConnector($tcp, $resolver); + } + + if ($options['tcp'] !== false) { + $options['tcp'] = $tcp; + + if ($options['timeout'] !== false) { + $options['tcp'] = new TimeoutConnector( + $options['tcp'], + $options['timeout'], + $loop + ); + } + + $this->connectors['tcp'] = $options['tcp']; + } + + if ($options['tls'] !== false) { + if (!$options['tls'] instanceof ConnectorInterface) { + $options['tls'] = new SecureConnector( + $tcp, + $loop, + is_array($options['tls']) ? $options['tls'] : array() + ); + } + + if ($options['timeout'] !== false) { + $options['tls'] = new TimeoutConnector( + $options['tls'], + $options['timeout'], + $loop + ); + } + + $this->connectors['tls'] = $options['tls']; + } + + if ($options['unix'] !== false) { + if (!$options['unix'] instanceof ConnectorInterface) { + $options['unix'] = new UnixConnector($loop); + } + $this->connectors['unix'] = $options['unix']; + } } public function connect($uri) { - return $this->connector->connect($uri); + $scheme = 'tcp'; + if (strpos($uri, '://') !== false) { + $scheme = (string)substr($uri, 0, strpos($uri, '://')); + } + + if (!isset($this->connectors[$scheme])) { + return Promise\reject(new RuntimeException( + 'No connector available for URI scheme "' . $scheme . '"' + )); + } + + return $this->connectors[$scheme]->connect($uri); } } + diff --git a/tests/ConnectorTest.php b/tests/ConnectorTest.php new file mode 100644 index 0000000..ea167ad --- /dev/null +++ b/tests/ConnectorTest.php @@ -0,0 +1,128 @@ +getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\SocketClient\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp + )); + + $connector->connect('127.0.0.1:80'); + } + + public function testConnectorPassedThroughHostnameIfDnsIsDisabled() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\SocketClient\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('tcp://google.com:80')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp, + 'dns' => false + )); + + $connector->connect('tcp://google.com:80'); + } + + public function testConnectorWithUnknownSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop); + + $promise = $connector->connect('unknown://google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTcpDefaultSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tcp' => false + )); + + $promise = $connector->connect('google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTcpSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tcp' => false + )); + + $promise = $connector->connect('tcp://google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTlsSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tls' => false + )); + + $promise = $connector->connect('tls://google.com:443'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledUnixSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'unix' => false + )); + + $promise = $connector->connect('unix://demo.sock'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorUsesGivenResolverInstance() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $resolver = $this->getMockBuilder('React\Dns\Resolver\Resolver')->disableOriginalConstructor()->getMock(); + $resolver->expects($this->once())->method('resolve')->with('google.com')->willReturn($promise); + + $connector = new Connector($loop, array( + 'dns' => $resolver + )); + + $connector->connect('google.com:80'); + } + + public function testConnectorUsesResolvedHostnameIfDnsIsUsed() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function ($resolve) { $resolve('127.0.0.1'); }); + $resolver = $this->getMockBuilder('React\Dns\Resolver\Resolver')->disableOriginalConstructor()->getMock(); + $resolver->expects($this->once())->method('resolve')->with('google.com')->willReturn($promise); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\SocketClient\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('tcp://127.0.0.1:80?hostname=google.com')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp, + 'dns' => $resolver + )); + + $connector->connect('tcp://google.com:80'); + } +} diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 6796874..a11447b 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -4,7 +4,6 @@ use React\Dns\Resolver\Factory; use React\EventLoop\StreamSelectLoop; -use React\Socket\Server; use React\SocketClient\Connector; use React\SocketClient\SecureConnector; use React\SocketClient\TcpConnector; @@ -20,10 +19,7 @@ class IntegrationTest extends TestCase public function gettingStuffFromGoogleShouldWork() { $loop = new StreamSelectLoop(); - - $factory = new Factory(); - $dns = $factory->create('8.8.8.8', $loop); - $connector = new Connector($loop, $dns); + $connector = new Connector($loop); $conn = Block\await($connector->connect('google.com:80'), $loop); @@ -45,16 +41,9 @@ public function gettingEncryptedStuffFromGoogleShouldWork() } $loop = new StreamSelectLoop(); + $secureConnector = new Connector($loop); - $factory = new Factory(); - $dns = $factory->create('8.8.8.8', $loop); - - $secureConnector = new SecureConnector( - new Connector($loop, $dns), - $loop - ); - - $conn = Block\await($secureConnector->connect('google.com:443'), $loop); + $conn = Block\await($secureConnector->connect('tls://google.com:443'), $loop); $conn->write("GET / HTTP/1.0\r\n\r\n"); @@ -93,7 +82,23 @@ public function gettingEncryptedStuffFromGoogleShouldWorkIfHostIsResolvedFirst() } /** @test */ - public function testSelfSignedRejectsIfVerificationIsEnabled() + public function testConnectingFailsIfDnsUsesInvalidResolver() + { + $loop = new StreamSelectLoop(); + + $factory = new Factory(); + $dns = $factory->create('demo.invalid', $loop); + + $connector = new Connector($loop, array( + 'dns' => $dns + )); + + $this->setExpectedException('RuntimeException'); + Block\await($connector->connect('google.com:80'), $loop, self::TIMEOUT); + } + + /** @test */ + public function testConnectingFailsIfTimeoutIsTooSmall() { if (!function_exists('stream_socket_enable_crypto')) { $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); @@ -101,19 +106,31 @@ public function testSelfSignedRejectsIfVerificationIsEnabled() $loop = new StreamSelectLoop(); - $factory = new Factory(); - $dns = $factory->create('8.8.8.8', $loop); + $connector = new Connector($loop, array( + 'timeout' => 0.001 + )); + + $this->setExpectedException('RuntimeException'); + Block\await($connector->connect('google.com:80'), $loop, self::TIMEOUT); + } - $secureConnector = new SecureConnector( - new Connector($loop, $dns), - $loop, - array( + /** @test */ + public function testSelfSignedRejectsIfVerificationIsEnabled() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = new StreamSelectLoop(); + + $connector = new Connector($loop, array( + 'tls' => array( 'verify_peer' => true ) - ); + )); $this->setExpectedException('RuntimeException'); - Block\await($secureConnector->connect('self-signed.badssl.com:443'), $loop, self::TIMEOUT); + Block\await($connector->connect('tls://self-signed.badssl.com:443'), $loop, self::TIMEOUT); } /** @test */ @@ -125,18 +142,13 @@ public function testSelfSignedResolvesIfVerificationIsDisabled() $loop = new StreamSelectLoop(); - $factory = new Factory(); - $dns = $factory->create('8.8.8.8', $loop); - - $secureConnector = new SecureConnector( - new Connector($loop, $dns), - $loop, - array( + $connector = new Connector($loop, array( + 'tls' => array( 'verify_peer' => false ) - ); + )); - $conn = Block\await($secureConnector->connect('self-signed.badssl.com:443'), $loop, self::TIMEOUT); + $conn = Block\await($connector->connect('tls://self-signed.badssl.com:443'), $loop, self::TIMEOUT); $conn->close(); }