Skip to content

Commit

Permalink
Update Socket to v0.7 and temporarily remove clue/socks until updated
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Apr 14, 2017
1 parent 06eaafd commit fac7430
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 96 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ $server = new Server($loop, $socket);
```

If you need custom connector settings (DNS resolution, timeouts etc.), you can explicitly pass a
custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket-client#connectorinterface):
custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):

```php
// use local DNS server
Expand Down Expand Up @@ -225,7 +225,7 @@ You can now create a SOCKS `Client` instance like this:

```php
// set next SOCKS server localhost:$targetPort as target
$connector = new React\SocketClient\TcpConnector($loop);
$connector = new React\Socket\TcpConnector($loop);
$client = new Clue\React\Socks\Client('user:pass@127.0.0.1:' . $targetPort, $connector);

// listen on localhost:$middlemanPort
Expand Down
8 changes: 2 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,13 @@
"require": {
"php": ">=5.3",
"react/event-loop": "0.3.*|0.4.*",
"react/socket-client": "^0.5.1",
"react/socket": "^0.5 || ^0.4.4",
"react/dns": "0.3.*|0.4.*",
"react/socket": "^0.7",
"react/stream": "^0.6 || ^0.5 || ^0.4.2",
"react/promise": "^2.1 || ^1.2",
"evenement/evenement": "~1.0|~2.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^4.8",
"clue/socks-react": "^0.6",
"clue/connection-manager-extra": "^0.5",
"react/socket": "^0.5"
"clue/connection-manager-extra": "^0.7"
}
}
9 changes: 3 additions & 6 deletions examples/03-server-blacklist.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
use React\Socket\Server as Socket;
use Clue\React\Socks\Server\Server;
use ConnectionManager\Extra\ConnectionManagerReject;
use React\SocketClient\Connector;
use React\Dns\Resolver\Factory;
use React\Socket\Connector;

require __DIR__ . '/../vendor/autoload.php';

Expand All @@ -19,10 +18,8 @@
// create a connector that rejects the connection
$reject = new ConnectionManagerReject();

// create an actual connector that establishes real connections (uses Google's public DNS)
$factory = new Factory();
$resolver = $factory->createCached('8.8.8.8', $loop);
$permit = new Connector($loop, $resolver);
// create an actual connector that establishes real connections
$permit = new Connector($loop);

// this connector selectively picks one of the the attached connectors depending on the target address
// reject youtube.com and unencrypted HTTP for google.com
Expand Down
2 changes: 1 addition & 1 deletion examples/11-server-proxy-chaining-with-password.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Clue\React\Socks\Client;
use Clue\React\Socks\Server\Server;
use React\Socket\Server as Socket;
use React\SocketClient\TcpConnector;
use React\Socket\TcpConnector;

include_once __DIR__.'/../vendor/autoload.php';

Expand Down
2 changes: 1 addition & 1 deletion examples/12-server-proxy-chaining-random-pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use React\Socket\Server as Socket;
use Clue\React\Socks\Server\Server;
use Clue\React\Socks\Client;
use React\SocketClient\TcpConnector;
use React\Socket\TcpConnector;

require __DIR__ . '/../vendor/autoload.php';

Expand Down
59 changes: 12 additions & 47 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
use React\Promise\Deferred;
use React\Promise\PromiseInterface;
use React\Promise\CancellablePromiseInterface;
use React\Stream\Stream;
use React\Stream\DuplexStreamInterface;
use React\Dns\Resolver\Factory as DnsFactory;
use React\SocketClient\ConnectorInterface;
use React\SocketClient\DnsConnector;
use React\SocketClient\TcpConnector;
use React\Socket\ConnectorInterface;
use React\Socket\Connector;
use React\Socket\ConnectionInterface;
use React\EventLoop\LoopInterface;
use \UnexpectedValueException;
Expand All @@ -34,10 +30,7 @@ class Server extends EventEmitter
public function __construct(LoopInterface $loop, ServerInterface $serverInterface, ConnectorInterface $connector = null)
{
if ($connector === null) {
// default to using Google's public DNS server
$dnsResolverFactory = new DnsFactory();
$resolver = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$connector = new DnsConnector(new TcpConnector($loop), $resolver);
$connector = new Connector($loop);
}

$this->loop = $loop;
Expand Down Expand Up @@ -116,10 +109,8 @@ public function onConnection(ConnectionInterface $connection)

/**
* gracefully shutdown connection by flushing all remaining data and closing stream
*
* @param Stream $stream
*/
public function endConnection(DuplexStreamInterface $stream)
public function endConnection(ConnectionInterface $stream)
{
$tid = true;
$loop = $this->loop;
Expand All @@ -146,7 +137,7 @@ public function endConnection(DuplexStreamInterface $stream)
}
}

private function handleSocks(DuplexStreamInterface $stream)
private function handleSocks(ConnectionInterface $stream)
{
$reader = new StreamReader();
$stream->on('data', array($reader, 'write'));
Expand Down Expand Up @@ -178,7 +169,7 @@ private function handleSocks(DuplexStreamInterface $stream)
});
}

public function handleSocks4(DuplexStreamInterface $stream, $protocolVersion, StreamReader $reader)
public function handleSocks4(ConnectionInterface $stream, $protocolVersion, StreamReader $reader)
{
// suppliying hostnames is only allowed for SOCKS4a (or automatically detected version)
$supportsHostname = ($protocolVersion === null || $protocolVersion === '4a');
Expand Down Expand Up @@ -210,7 +201,7 @@ public function handleSocks4(DuplexStreamInterface $stream, $protocolVersion, St
return array($ip, $data['port']);
}
})->then(function ($target) use ($stream, $that) {
return $that->connectTarget($stream, $target)->then(function (Stream $remote) use ($stream){
return $that->connectTarget($stream, $target)->then(function (ConnectionInterface $remote) use ($stream){
$stream->write(pack('C8', 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));

return $remote;
Expand All @@ -224,7 +215,7 @@ public function handleSocks4(DuplexStreamInterface $stream, $protocolVersion, St
});
}

public function handleSocks5(DuplexStreamInterface $stream, $auth=null, StreamReader $reader)
public function handleSocks5(ConnectionInterface $stream, $auth=null, StreamReader $reader)
{
$that = $this;
return $reader->readByte()->then(function ($num) use ($reader) {
Expand Down Expand Up @@ -307,7 +298,7 @@ public function handleSocks5(DuplexStreamInterface $stream, $auth=null, StreamRe
return $that->connectTarget($stream, $target);
}, function($error) use ($stream) {
throw new UnexpectedValueException('SOCKS5 protocol error',0,$error);
})->then(function (Stream $remote) use ($stream) {
})->then(function (ConnectionInterface $remote) use ($stream) {
$stream->write(pack('C4Nn', 0x05, 0x00, 0x00, 0x01, 0, 0));

return $remote;
Expand All @@ -319,17 +310,17 @@ public function handleSocks5(DuplexStreamInterface $stream, $auth=null, StreamRe
});
}

public function connectTarget(DuplexStreamInterface $stream, array $target)
public function connectTarget(ConnectionInterface $stream, array $target)
{
$stream->emit('target', $target);
$that = $this;
$connecting = $this->connect($target[0], $target[1]);
$connecting = $this->connector->connect($target[0] . ':' . $target[1]);

$stream->on('close', function () use ($connecting) {
$connecting->cancel();
});

return $connecting->then(function (Stream $remote) use ($stream, $that) {
return $connecting->then(function (ConnectionInterface $remote) use ($stream, $that) {
$stream->pipe($remote, array('end'=>false));
$remote->pipe($stream, array('end'=>false));

Expand All @@ -352,30 +343,4 @@ public function connectTarget(DuplexStreamInterface $stream, array $target)
throw new UnexpectedValueException('Unable to connect to remote target', 0, $error);
});
}

private function connect($host, $port)
{
$promise = $this->connector->create($host, $port);

return new Promise\Promise(
function ($resolve, $reject) use ($promise) {
// resolve/reject with result of TCP/IP connection
$promise->then($resolve, $reject);
},
function ($_, $reject) use ($promise) {
// cancellation should reject connection attempt
$reject(new RuntimeException('Connection attempt cancelled'));

// forefully close TCP/IP connection if it completes despite cancellation
$promise->then(function (Stream $stream) {
$stream->close();
});

// (try to) cancel pending TCP/IP connection
if ($promise instanceof CancellablePromiseInterface) {
$promise->cancel();
}
}
);
}
}
8 changes: 5 additions & 3 deletions tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
use Clue\React\Socks\Client;
use Clue\React\Socks\Server\Server;
use React\Promise\PromiseInterface;
use React\SocketClient\TimeoutConnector;
use React\SocketClient\SecureConnector;
use React\SocketClient\TcpConnector;
use React\Socket\TimeoutConnector;
use React\Socket\SecureConnector;
use React\Socket\TcpConnector;

class FunctionalTest extends TestCase
{
Expand All @@ -18,6 +18,8 @@ class FunctionalTest extends TestCase

public function setUp()
{
$this->markTestSkipped();

$this->loop = React\EventLoop\Factory::create();

$socket = new React\Socket\Server(0, $this->loop);
Expand Down
49 changes: 19 additions & 30 deletions tests/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ public function setUp()
$socket = $this->getMockBuilder('React\Socket\ServerInterface')
->getMock();

$loop = $this->getMockBuilder('React\EventLoop\StreamSelectLoop')
->disableOriginalConstructor()
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')
->getMock();

$this->connector = $this->getMockBuilder('React\SocketClient\Connector')
->disableOriginalConstructor()
$this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')
->getMock();

$this->server = new Server($loop, $socket, $this->connector);
Expand Down Expand Up @@ -85,11 +83,11 @@ public function testUnableToSetProtocolWhichDoesNotSupportAuth()

public function testConnectWillCreateConnection()
{
$stream = $this->getMockBuilder('React\Stream\Stream')->disableOriginalConstructor()->getMock();
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();

$promise = new Promise(function () { });

$this->connector->expects($this->once())->method('create')->with('google.com', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);

$promise = $this->server->connectTarget($stream, array('google.com', 80));

Expand All @@ -98,11 +96,11 @@ public function testConnectWillCreateConnection()

public function testConnectWillRejectIfConnectionFails()
{
$stream = $this->getMockBuilder('React\Stream\Stream')->disableOriginalConstructor()->getMock();
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();

$promise = new Promise(function ($_, $reject) { $reject(new \RuntimeException()); });

$this->connector->expects($this->once())->method('create')->with('google.com', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);

$promise = $this->server->connectTarget($stream, array('google.com', 80));

Expand All @@ -111,11 +109,14 @@ public function testConnectWillRejectIfConnectionFails()

public function testConnectWillCancelConnectionIfStreamCloses()
{
$stream = $this->getMockBuilder('React\Stream\Stream')->disableOriginalConstructor()->setMethods(array('close'))->getMock();
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close'))->getMock();

$promise = new Promise(function () { }, function () {
throw new \RuntimeException();
});

$promise = new Promise(function () { }, $this->expectCallableOnce());

$this->connector->expects($this->once())->method('create')->with('google.com', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);

$promise = $this->server->connectTarget($stream, array('google.com', 80));

Expand All @@ -126,11 +127,13 @@ public function testConnectWillCancelConnectionIfStreamCloses()

public function testConnectWillAbortIfPromiseIsCancelled()
{
$stream = $this->getMockBuilder('React\Stream\Stream')->disableOriginalConstructor()->getMock();
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();

$promise = new Promise(function () { }, $this->expectCallableOnce());
$promise = new Promise(function () { }, function () {
throw new \RuntimeException();
});

$this->connector->expects($this->once())->method('create')->with('google.com', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);

$promise = $this->server->connectTarget($stream, array('google.com', 80));

Expand All @@ -139,20 +142,6 @@ public function testConnectWillAbortIfPromiseIsCancelled()
$promise->then(null, $this->expectCallableOnce());
}

public function testConnectWillCloseStreamIfConnectorResolvesDespiteCancellation()
{
$stream = $this->getMockBuilder('React\Stream\Stream')->disableOriginalConstructor()->getMock();
$stream->expects($this->once())->method('close');

$promise = new Promise(function () { }, function ($resolve) use ($stream) { $resolve($stream); });

$this->connector->expects($this->once())->method('create')->with('google.com', 80)->willReturn($promise);

$promise = $this->server->connectTarget($stream, array('google.com', 80));

$promise->cancel();
}

public function testHandleSocksConnectionWillEndOnInvalidData()
{
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
Expand All @@ -170,7 +159,7 @@ public function testHandleSocksConnectionWillEstablishOutgoingConnection()

$promise = new Promise(function () { });

$this->connector->expects($this->once())->method('create')->with('127.0.0.1', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);

$this->server->onConnection($connection);

Expand All @@ -183,7 +172,7 @@ public function testHandleSocksConnectionWillCancelOutputConnectionIfIncomingClo

$promise = new Promise(function () { }, $this->expectCallableOnce());

$this->connector->expects($this->once())->method('create')->with('127.0.0.1', 80)->willReturn($promise);
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);

$this->server->onConnection($connection);

Expand Down

0 comments on commit fac7430

Please sign in to comment.