Skip to content

Commit

Permalink
Merge branch 'master' into uri
Browse files Browse the repository at this point in the history
  • Loading branch information
clue authored Jan 5, 2017
2 parents 5414f98 + 5570838 commit 035b373
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 29 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## 0.5.3 (2016-12-24)

* Fix: Skip IPv6 tests if not supported by the system
(#76 by @clue)

* Documentation for `ConnectorInterface`
(#77 by @clue)

## 0.5.2 (2016-12-19)

* Feature: Replace `SecureStream` with unlimited read buffer from react/stream v0.4.5
(#72 by @clue)

* Feature: Add examples
(#75 by @clue)

## 0.5.1 (2016-11-20)

* Feature: Support Promise cancellation for all connectors
Expand Down
100 changes: 74 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,57 @@ to initialize the main loop.
$loop = React\EventLoop\Factory::create();
```

### ConnectorInterface

The `ConnectorInterface` is responsible for providing an interface for
establishing streaming connections, such as a normal TCP/IP connection.

This is the main interface defined in this package and it is used throughout
React's vast ecosystem.

Most higher-level components (such as HTTP, database or other networking
service clients) accept an instance implementing this interface to create their
TCP/IP connection to the underlying networking service.
This is usually done via dependency injection, so it's fairly simple to actually
swap this implementation against any other implementation of this interface.

The interface only offers a single method:

#### connect()

The `connect(string $uri): PromiseInterface<Stream, Exception>` method
can be used to establish a streaming connection.
It returns a [Promise](https://github.com/reactphp/promise) which either
fulfills with a [Stream](https://github.com/reactphp/stream) or
rejects with an `Exception`:

```php
$connector->connect('google.com:443')->then(
function (Stream $stream) {
// connection successfully established
},
function (Exception $error) {
// failed to connect due to $error
}
);
```

The returned Promise SHOULD be implemented in such a way that it can be
cancelled when it is still pending. Cancelling a pending promise SHOULD
reject its value with an `Exception`. It SHOULD clean up any underlying
resources and references as applicable:

```php
$promise = $connector->connect($uri);

$promise->cancel();
```

### Async TCP/IP connections

The `React\SocketClient\TcpConnector` provides a single promise-based
`connect($uri)` method which resolves as soon as the connection
succeeds or fails.
The `React\SocketClient\TcpConnector` class implements the
[`ConnectorInterface`](#connectorinterface) and allows you to create plaintext
TCP/IP connections to any IP-port-combination:

```php
$tcpConnector = new React\SocketClient\TcpConnector($loop);
Expand Down Expand Up @@ -69,17 +115,18 @@ $tcpConnector = new React\SocketClient\TcpConnector($loop, array(
));
```

Note that this class only allows you to connect to IP/port combinations.
If you want to connect to hostname/port combinations, see also the following chapter.
Note that this class only allows you to connect to IP-port-combinations.
If you want to connect to hostname-port-combinations, see also the following chapter.

### DNS resolution

The `DnsConnector` class decorates a given `TcpConnector` instance by first
looking up the given domain name and then establishing the underlying TCP/IP
connection to the resolved IP address.
The `DnsConnector` class implements the
[`ConnectorInterface`](#connectorinterface) and allows you to create plaintext
TCP/IP connections to any hostname-port-combination.

It provides the same promise-based `connect($uri)` method which resolves with
a `Stream` instance that can be used just like above.
It does so by decorating a given `TcpConnector` instance so that it first
looks up the given domain name via DNS (if applicable) and then establishes the
underlying TCP/IP connection to the resolved target IP address.

Make sure to set up your DNS resolver and underlying TCP connector like this:

Expand Down Expand Up @@ -122,11 +169,13 @@ $connector->connect('www.google.com:80')->then($callback);

### Async SSL/TLS connections

The `SecureConnector` class decorates a given `Connector` instance by enabling
SSL/TLS encryption as soon as the raw TCP/IP connection succeeds.
The `SecureConnector` class implements the
[`ConnectorInterface`](#connectorinterface) and allows you to create secure
TLS (formerly known as SSL) connections to any hostname-port-combination.

It provides the same promise- based `connect($uri)` method which resolves with
a `Stream` instance that can be used just like any non-encrypted stream:
It does so by decorating a given `DnsConnector` instance so that it first
creates a plaintext TCP/IP connection and then enables TLS encryption on this
stream.

```php
$secureConnector = new React\SocketClient\SecureConnector($dnsConnector, $loop);
Expand Down Expand Up @@ -173,8 +222,12 @@ stream resources will use a single, shared *default context* resource otherwise.

### Connection timeouts

The `TimeoutConnector` class decorates any given `Connector` instance.
It provides the same `connect($uri)` method, but will automatically reject the
The `TimeoutConnector` class implements the
[`ConnectorInterface`](#connectorinterface) and allows you to add timeout
handling to any existing connector instance.

It does so by decorating any given [`ConnectorInterface`](#connectorinterface)
instance and starting a timer that will automatically reject and abort any
underlying connection attempt if it takes too long.

```php
Expand All @@ -200,8 +253,9 @@ attempt, abort the timer and reject the resulting promise.

### Unix domain sockets

Similarly, the `UnixConnector` class can be used to connect to Unix domain socket (UDS)
paths like this:
The `UnixConnector` class implements the
[`ConnectorInterface`](#connectorinterface) and allows you to connect to
Unix domain socket (UDS) paths like this:

```php
$connector = new React\SocketClient\UnixConnector($loop);
Expand All @@ -225,16 +279,10 @@ The recommended way to install this library is [through Composer](http://getcomp
This will install the latest supported version:

```bash
$ composer require react/socket-client:^0.5.1
```

If you care a lot about BC, you may also want to look into supporting legacy versions:

```bash
$ composer require "react/socket-client:^0.5||^0.4||^0.3"
$ composer require react/socket-client:^0.5.3
```

More details and upgrade guides can be found in the [CHANGELOG](CHANGELOG.md).
More details about version upgrades can be found in the [CHANGELOG](CHANGELOG.md).

## Tests

Expand Down
7 changes: 7 additions & 0 deletions src/Connector.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
use React\Dns\Resolver\Resolver;

/**
* Legacy Connector
*
* This class is not to be confused with the ConnectorInterface and should not
* be used as a typehint.
*
* @deprecated Exists for BC only, consider using the newer DnsConnector instead
* @see DnsConnector for the newer replacement
* @see ConnectorInterface for the base interface
*/
class Connector implements ConnectorInterface
{
Expand Down
26 changes: 24 additions & 2 deletions src/ConnectorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,36 @@

namespace React\SocketClient;

/**
* The `ConnectorInterface` is responsible for providing an interface for
* establishing streaming connections, such as a normal TCP/IP connection.
*
* This is the main interface defined in this package and it is used throughout
* React's vast ecosystem.
*
* Most higher-level components (such as HTTP, database or other networking
* service clients) accept an instance implementing this interface to create their
* TCP/IP connection to the underlying networking service.
* This is usually done via dependency injection, so it's fairly simple to actually
* swap this implementation against any other implementation of this interface.
*
* The interface only offers a single `connect()` method.
*/
interface ConnectorInterface
{
/**
* Creates a Promise which resolves with a stream once the connection to the given remote address succeeds
*
* The Promise resolves with a `React\Stream\Stream` instance on success or
* rejects with an `Exception` if the connection is not successful.
*
* The returned Promise SHOULD be implemented in such a way that it can be
* cancelled when it is still pending. Cancelling a pending promise SHOULD
* reject its value with an Exception. It SHOULD clean up any underlying
* resources and references as applicable.
*
* @param string $uri
* @return Promise Returns a Promise<\React\Stream\Stream, \Exception>, i.e.
* it either resolves with a Stream instance or rejects with an Exception.
* @return React\Promise\PromiseInterface resolves with a Stream on success or rejects with an Exception on error
*/
public function connect($uri);
}
7 changes: 6 additions & 1 deletion tests/TcpConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ public function connectionToIp6TcpServerShouldSucceed()
$server = new Server($loop);
$server->on('connection', $this->expectCallableOnce());
$server->on('connection', array($server, 'shutdown'));
$server->listen(9999, '::1');

try {
$server->listen(9999, '::1');
} catch (\Exception $e) {
$this->markTestSkipped('Unable to start IPv6 server socket (IPv6 not supported on this system?)');
}

$connector = new TcpConnector($loop);

Expand Down

0 comments on commit 035b373

Please sign in to comment.