diff --git a/README.md b/README.md index 5a505f0..ee49a12 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/composer.json b/composer.json index 446de60..9cc8c54 100644 --- a/composer.json +++ b/composer.json @@ -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" } } diff --git a/examples/03-server-blacklist.php b/examples/03-server-blacklist.php index c5a90c9..3d0bedb 100644 --- a/examples/03-server-blacklist.php +++ b/examples/03-server-blacklist.php @@ -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'; @@ -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 diff --git a/examples/11-server-proxy-chaining-with-password.php b/examples/11-server-proxy-chaining-with-password.php index 6a67fca..9c222d3 100644 --- a/examples/11-server-proxy-chaining-with-password.php +++ b/examples/11-server-proxy-chaining-with-password.php @@ -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'; diff --git a/examples/12-server-proxy-chaining-random-pool.php b/examples/12-server-proxy-chaining-random-pool.php index be885c6..040a8f3 100644 --- a/examples/12-server-proxy-chaining-random-pool.php +++ b/examples/12-server-proxy-chaining-random-pool.php @@ -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'; diff --git a/src/Server.php b/src/Server.php index 5fda97b..76ae479 100644 --- a/src/Server.php +++ b/src/Server.php @@ -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; @@ -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; @@ -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; @@ -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')); @@ -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'); @@ -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; @@ -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) { @@ -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; @@ -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)); @@ -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(); - } - } - ); - } } diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 2868bd8..7bcb771 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -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 { @@ -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); diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 05db190..8c8f67a 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -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); @@ -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)); @@ -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)); @@ -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)); @@ -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)); @@ -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(); @@ -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); @@ -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);