init
This commit is contained in:
403
vendor/clue/socks-react/tests/ClientTest.php
vendored
Executable file
403
vendor/clue/socks-react/tests/ClientTest.php
vendored
Executable file
@@ -0,0 +1,403 @@
|
||||
<?php
|
||||
|
||||
use Clue\React\Socks\Client;
|
||||
use React\Promise\Promise;
|
||||
use Clue\React\Socks\Server;
|
||||
|
||||
class ClientTest extends TestCase
|
||||
{
|
||||
private $loop;
|
||||
|
||||
private $connector;
|
||||
|
||||
/** @var Client */
|
||||
private $client;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = React\EventLoop\Factory::create();
|
||||
$this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
|
||||
$this->client = new Client('127.0.0.1:1080', $this->connector);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithHostAndPort()
|
||||
{
|
||||
$client = new Client('127.0.0.1:9050', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithScheme()
|
||||
{
|
||||
$client = new Client('socks://127.0.0.1:9050', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithHostOnlyAssumesDefaultPort()
|
||||
{
|
||||
$client = new Client('127.0.0.1', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithSecureScheme()
|
||||
{
|
||||
$client = new Client('sockss://127.0.0.1:9050', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithSecureVersionScheme()
|
||||
{
|
||||
$client = new Client('socks5s://127.0.0.1:9050', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithSocksUnixScheme()
|
||||
{
|
||||
$client = new Client('socks+unix:///tmp/socks.socket', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testCtorAcceptsUriWithSocks5UnixScheme()
|
||||
{
|
||||
$client = new Client('socks5+unix:///tmp/socks.socket', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testCtorThrowsForInvalidUri()
|
||||
{
|
||||
new Client('////', $this->connector);
|
||||
}
|
||||
|
||||
public function testValidAuthFromUri()
|
||||
{
|
||||
$this->client = new Client('username:password@127.0.0.1', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidAuthInformation()
|
||||
{
|
||||
new Client(str_repeat('a', 256) . ':test@127.0.0.1', $this->connector);
|
||||
}
|
||||
|
||||
public function testValidAuthAndVersionFromUri()
|
||||
{
|
||||
$this->client = new Client('socks5://username:password@127.0.0.1:9050', $this->connector);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidCanNotSetAuthenticationForSocks4Uri()
|
||||
{
|
||||
$this->client = new Client('socks4://username:password@127.0.0.1:9050', $this->connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidProtocolVersion()
|
||||
{
|
||||
$this->client = new Client('socks3://127.0.0.1:9050', $this->connector);
|
||||
}
|
||||
|
||||
public function testCreateWillConnectToProxy()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=localhost')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('localhost:80');
|
||||
|
||||
$this->assertInstanceOf('\React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testCreateWillConnectToProxyWithFullUri()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080/?hostname=test#fragment')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('localhost:80/?hostname=test#fragment');
|
||||
|
||||
$this->assertInstanceOf('\React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testCreateWithInvalidHostDoesNotConnect()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$promise = $this->client->connect(str_repeat('a', '256') . ':80');
|
||||
|
||||
$this->assertInstanceOf('\React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testCreateWithInvalidPortDoesNotConnect()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$promise = $this->client->connect('some-random-site:some-random-port');
|
||||
|
||||
$this->assertInstanceOf('\React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testConnectorRejectsWillRejectConnection()
|
||||
{
|
||||
$promise = \React\Promise\reject(new RuntimeException());
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNREFUSED));
|
||||
}
|
||||
|
||||
public function testCancelConnectionDuringConnectionWillCancelConnection()
|
||||
{
|
||||
$promise = new Promise(function () { }, function () {
|
||||
throw new \RuntimeException();
|
||||
});
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
$promise->cancel();
|
||||
|
||||
$this->expectPromiseReject($promise);
|
||||
}
|
||||
|
||||
public function testCancelConnectionDuringSessionWillCloseStream()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = new Promise(function ($resolve) use ($stream) { $resolve($stream); });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNABORTED));
|
||||
}
|
||||
|
||||
public function testEmitConnectionCloseDuringSessionWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('close');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNRESET));
|
||||
}
|
||||
|
||||
public function testEmitConnectionErrorDuringSessionWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('error', array(new RuntimeException()));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EIO));
|
||||
}
|
||||
|
||||
public function testEmitInvalidSocks4DataDuringSessionWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("HTTP/1.1 400 Bad Request\r\n\r\n"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EBADMSG));
|
||||
}
|
||||
|
||||
public function testEmitInvalidSocks5DataDuringSessionWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("HTTP/1.1 400 Bad Request\r\n\r\n"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EBADMSG));
|
||||
}
|
||||
|
||||
public function testEmitSocks5DataErrorDuringSessionWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("\x05\x00" . "\x05\x01\x00\x00"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNREFUSED));
|
||||
}
|
||||
|
||||
public function testEmitSocks5DataInvalidAddressTypeWillRejectConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("\x05\x00" . "\x05\x00\x00\x00"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EBADMSG));
|
||||
}
|
||||
|
||||
public function testEmitSocks5DataIpv6AddressWillResolveConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->never())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=%3A%3A1')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('[::1]:80');
|
||||
|
||||
$stream->emit('data', array("\x05\x00" . "\x05\x00\x00\x04" . inet_pton('::1') . "\x00\x50"));
|
||||
|
||||
$promise->then($this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testEmitSocks5DataHostnameAddressWillResolveConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->never())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("\x05\x00" . "\x05\x00\x00\x03\x0Agoogle.com\x00\x50"));
|
||||
|
||||
$promise->then($this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function provideConnectionErrors()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
Server::ERROR_GENERAL,
|
||||
SOCKET_ECONNREFUSED
|
||||
),
|
||||
array(
|
||||
Server::ERROR_NOT_ALLOWED_BY_RULESET,
|
||||
SOCKET_EACCES
|
||||
),
|
||||
array(
|
||||
Server::ERROR_NETWORK_UNREACHABLE,
|
||||
SOCKET_ENETUNREACH
|
||||
),
|
||||
array(
|
||||
Server::ERROR_HOST_UNREACHABLE,
|
||||
SOCKET_EHOSTUNREACH
|
||||
),
|
||||
array(
|
||||
Server::ERROR_CONNECTION_REFUSED,
|
||||
SOCKET_ECONNREFUSED
|
||||
),
|
||||
array(
|
||||
Server::ERROR_TTL,
|
||||
SOCKET_ETIMEDOUT
|
||||
),
|
||||
array(
|
||||
Server::ERROR_COMMAND_UNSUPPORTED,
|
||||
SOCKET_EPROTO
|
||||
),
|
||||
array(
|
||||
Server::ERROR_ADDRESS_UNSUPPORTED,
|
||||
SOCKET_EPROTO
|
||||
),
|
||||
array(
|
||||
200,
|
||||
SOCKET_ECONNREFUSED
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideConnectionErrors
|
||||
* @param int $error
|
||||
* @param int $expectedCode
|
||||
*/
|
||||
public function testEmitSocks5DataErrorMapsToExceptionCode($error, $expectedCode)
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:1080', $this->connector);
|
||||
|
||||
$promise = $this->client->connect('google.com:80');
|
||||
|
||||
$stream->emit('data', array("\x05\x00" . "\x05" . chr($error) . "\x00\x00"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode($expectedCode));
|
||||
}
|
||||
}
|
||||
437
vendor/clue/socks-react/tests/FunctionalTest.php
vendored
Executable file
437
vendor/clue/socks-react/tests/FunctionalTest.php
vendored
Executable file
@@ -0,0 +1,437 @@
|
||||
<?php
|
||||
|
||||
use Clue\React\Socks\Client;
|
||||
use Clue\React\Socks\Server;
|
||||
use Clue\React\Block;
|
||||
use React\Socket\TimeoutConnector;
|
||||
use React\Socket\SecureConnector;
|
||||
use React\Socket\TcpConnector;
|
||||
use React\Socket\UnixServer;
|
||||
use React\Socket\Connector;
|
||||
|
||||
class FunctionalTest extends TestCase
|
||||
{
|
||||
private $loop;
|
||||
private $connector;
|
||||
private $client;
|
||||
|
||||
private $port;
|
||||
private $server;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = React\EventLoop\Factory::create();
|
||||
|
||||
$socket = new React\Socket\Server(0, $this->loop);
|
||||
$address = $socket->getAddress();
|
||||
if (strpos($address, '://') === false) {
|
||||
$address = 'tcp://' . $address;
|
||||
}
|
||||
$this->port = parse_url($address, PHP_URL_PORT);
|
||||
$this->assertNotEquals(0, $this->port);
|
||||
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
$this->connector = new TcpConnector($this->loop);
|
||||
$this->client = new Client('127.0.0.1:' . $this->port, $this->connector);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnection()
|
||||
{
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionInvalid()
|
||||
{
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com.invalid:80'));
|
||||
}
|
||||
|
||||
public function testConnectionWithIpViaSocks4()
|
||||
{
|
||||
$this->server->setProtocolVersion('4');
|
||||
|
||||
$this->client = new Client('socks4://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('127.0.0.1:' . $this->port));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionWithHostnameViaSocks4Fails()
|
||||
{
|
||||
$this->client = new Client('socks4://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionWithInvalidPortFails()
|
||||
{
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:100000'));
|
||||
}
|
||||
|
||||
public function testConnectionWithIpv6ViaSocks4Fails()
|
||||
{
|
||||
$this->client = new Client('socks4://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('[::1]:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocks4a()
|
||||
{
|
||||
$this->server->setProtocolVersion('4a');
|
||||
$this->client = new Client('socks4a://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocks5()
|
||||
{
|
||||
$this->server->setProtocolVersion(5);
|
||||
$this->client = new Client('socks5://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocksOverTls()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$socket = new \React\Socket\Server('tls://127.0.0.1:0', $this->loop, array('tls' => array(
|
||||
'local_cert' => __DIR__ . '/../examples/localhost.pem',
|
||||
)));
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
|
||||
$this->connector = new Connector($this->loop, array('tls' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
)));
|
||||
$this->client = new Client(str_replace('tls:', 'sockss:', $socket->getAddress()), $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group internet
|
||||
* @requires PHP 5.6
|
||||
*/
|
||||
public function testConnectionSocksOverTlsUsesPeerNameFromSocksUri()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$socket = new \React\Socket\Server('tls://127.0.0.1:0', $this->loop, array('tls' => array(
|
||||
'local_cert' => __DIR__ . '/../examples/localhost.pem',
|
||||
)));
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
|
||||
$this->connector = new Connector($this->loop, array('tls' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => true
|
||||
)));
|
||||
$this->client = new Client(str_replace('tls:', 'sockss:', $socket->getAddress()), $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocksOverUnix()
|
||||
{
|
||||
if (!in_array('unix', stream_get_transports())) {
|
||||
$this->markTestSkipped('System does not support unix:// scheme');
|
||||
}
|
||||
|
||||
$path = sys_get_temp_dir() . '/test' . mt_rand(1000, 9999) . '.sock';
|
||||
$socket = new UnixServer($path, $this->loop);
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
|
||||
$this->connector = new Connector($this->loop);
|
||||
$this->client = new Client('socks+unix://' . $path, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocks5OverUnix()
|
||||
{
|
||||
if (!in_array('unix', stream_get_transports())) {
|
||||
$this->markTestSkipped('System does not support unix:// scheme');
|
||||
}
|
||||
|
||||
$path = sys_get_temp_dir() . '/test' . mt_rand(1000, 9999) . '.sock';
|
||||
$socket = new UnixServer($path, $this->loop);
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
$this->server->setProtocolVersion(5);
|
||||
|
||||
$this->connector = new Connector($this->loop);
|
||||
$this->client = new Client('socks5+unix://' . $path, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionSocksWithAuthenticationOverUnix()
|
||||
{
|
||||
if (!in_array('unix', stream_get_transports())) {
|
||||
$this->markTestSkipped('System does not support unix:// scheme');
|
||||
}
|
||||
|
||||
$path = sys_get_temp_dir() . '/test' . mt_rand(1000, 9999) . '.sock';
|
||||
$socket = new UnixServer($path, $this->loop);
|
||||
$this->server = new Server($this->loop, $socket);
|
||||
$this->server->setAuthArray(array('name' => 'pass'));
|
||||
|
||||
$this->connector = new Connector($this->loop);
|
||||
$this->client = new Client('socks+unix://name:pass@' . $path, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationFromUri()
|
||||
{
|
||||
$this->server->setAuthArray(array('name' => 'pass'));
|
||||
|
||||
$this->client = new Client('name:pass@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationCallback()
|
||||
{
|
||||
$called = 0;
|
||||
$that = $this;
|
||||
$this->server->setAuth(function ($name, $pass, $remote) use ($that, &$called) {
|
||||
++$called;
|
||||
$that->assertEquals('name', $name);
|
||||
$that->assertEquals('pass', $pass);
|
||||
$that->assertStringStartsWith('socks5://name:pass@127.0.0.1:', $remote);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$this->client = new Client('name:pass@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
$this->assertEquals(1, $called);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationCallbackWillNotBeInvokedIfClientsSendsNoAuth()
|
||||
{
|
||||
$called = 0;
|
||||
$this->server->setAuth(function () use (&$called) {
|
||||
++$called;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$this->client = new Client('127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'));
|
||||
$this->assertEquals(0, $called);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationFromUriEncoded()
|
||||
{
|
||||
$this->server->setAuthArray(array('name' => 'p@ss:w0rd'));
|
||||
|
||||
$this->client = new Client(rawurlencode('name') . ':' . rawurlencode('p@ss:w0rd') . '@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationFromUriWithOnlyUserAndNoPassword()
|
||||
{
|
||||
$this->server->setAuthArray(array('empty' => ''));
|
||||
|
||||
$this->client = new Client('empty@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationEmptyPassword()
|
||||
{
|
||||
$this->server->setAuthArray(array('user' => ''));
|
||||
$this->client = new Client('user@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectionAuthenticationUnused()
|
||||
{
|
||||
$this->client = new Client('name:pass@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
public function testConnectionInvalidProtocolDoesNotMatchSocks5()
|
||||
{
|
||||
$this->server->setProtocolVersion(5);
|
||||
$this->client = new Client('socks4a://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'), null, SOCKET_ECONNRESET);
|
||||
}
|
||||
|
||||
public function testConnectionInvalidProtocolDoesNotMatchSocks4()
|
||||
{
|
||||
$this->server->setProtocolVersion(4);
|
||||
$this->client = new Client('socks5://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'), null, SOCKET_ECONNRESET);
|
||||
}
|
||||
|
||||
public function testConnectionInvalidNoAuthentication()
|
||||
{
|
||||
$this->server->setAuthArray(array('name' => 'pass'));
|
||||
|
||||
$this->client = new Client('socks5://127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'), null, SOCKET_EACCES);
|
||||
}
|
||||
|
||||
public function testConnectionInvalidAuthenticationMismatch()
|
||||
{
|
||||
$this->server->setAuthArray(array('name' => 'pass'));
|
||||
|
||||
$this->client = new Client('user:pass@127.0.0.1:' . $this->port, $this->connector);
|
||||
|
||||
$this->assertRejectPromise($this->client->connect('www.google.com:80'), null, SOCKET_EACCES);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectorOkay()
|
||||
{
|
||||
$this->assertResolveStream($this->client->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectorInvalidDomain()
|
||||
{
|
||||
$this->assertRejectPromise($this->client->connect('www.google.commm:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectorCancelConnection()
|
||||
{
|
||||
$promise = $this->client->connect('www.google.com:80');
|
||||
$promise->cancel();
|
||||
|
||||
$this->assertRejectPromise($promise);
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testConnectorInvalidUnboundPortTimeout()
|
||||
{
|
||||
// time out the connection attempt in 0.1s (as expected)
|
||||
$tcp = new TimeoutConnector($this->client, 0.1, $this->loop);
|
||||
|
||||
$this->assertRejectPromise($tcp->connect('www.google.com:8080'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testSecureConnectorOkay()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$ssl = new SecureConnector($this->client, $this->loop);
|
||||
|
||||
$this->assertResolveStream($ssl->connect('www.google.com:443'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testSecureConnectorToBadSslWithVerifyFails()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$ssl = new SecureConnector($this->client, $this->loop, array('verify_peer' => true));
|
||||
|
||||
$this->assertRejectPromise($ssl->connect('self-signed.badssl.com:443'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testSecureConnectorToBadSslWithoutVerifyWorks()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$ssl = new SecureConnector($this->client, $this->loop, array('verify_peer' => false));
|
||||
|
||||
$this->assertResolveStream($ssl->connect('self-signed.badssl.com:443'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testSecureConnectorInvalidPlaintextIsNotSsl()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('Required function does not exist in your environment (HHVM?)');
|
||||
}
|
||||
|
||||
$ssl = new SecureConnector($this->client, $this->loop);
|
||||
|
||||
$this->assertRejectPromise($ssl->connect('www.google.com:80'));
|
||||
}
|
||||
|
||||
/** @group internet */
|
||||
public function testSecureConnectorInvalidUnboundPortTimeout()
|
||||
{
|
||||
$ssl = new SecureConnector($this->client, $this->loop);
|
||||
|
||||
// time out the connection attempt in 0.1s (as expected)
|
||||
$ssl = new TimeoutConnector($ssl, 0.1, $this->loop);
|
||||
|
||||
$this->assertRejectPromise($ssl->connect('www.google.com:8080'));
|
||||
}
|
||||
|
||||
private function assertResolveStream($promise)
|
||||
{
|
||||
$this->expectPromiseResolve($promise);
|
||||
|
||||
$promise->then(function ($stream) {
|
||||
$stream->close();
|
||||
});
|
||||
|
||||
Block\await($promise, $this->loop, 2.0);
|
||||
}
|
||||
|
||||
private function assertRejectPromise($promise, $message = null, $code = null)
|
||||
{
|
||||
$this->expectPromiseReject($promise);
|
||||
|
||||
if (method_exists($this, 'expectException')) {
|
||||
$this->expectException('Exception');
|
||||
if ($message !== null) {
|
||||
$this->expectExceptionMessage($message);
|
||||
}
|
||||
if ($code !== null) {
|
||||
$this->expectExceptionCode($code);
|
||||
}
|
||||
} else {
|
||||
$this->setExpectedException('Exception', $message, $code);
|
||||
}
|
||||
|
||||
Block\await($promise, $this->loop, 2.0);
|
||||
}
|
||||
}
|
||||
428
vendor/clue/socks-react/tests/ServerTest.php
vendored
Executable file
428
vendor/clue/socks-react/tests/ServerTest.php
vendored
Executable file
@@ -0,0 +1,428 @@
|
||||
<?php
|
||||
|
||||
use Clue\React\Socks\Server;
|
||||
use React\Promise\Promise;
|
||||
use React\Promise\Timer\TimeoutException;
|
||||
|
||||
class ServerTest extends TestCase
|
||||
{
|
||||
/** @var Server */
|
||||
private $server;
|
||||
private $connector;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$socket = $this->getMockBuilder('React\Socket\ServerInterface')
|
||||
->getMock();
|
||||
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')
|
||||
->getMock();
|
||||
|
||||
$this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')
|
||||
->getMock();
|
||||
|
||||
$this->server = new Server($loop, $socket, $this->connector);
|
||||
}
|
||||
|
||||
public function testSetProtocolVersion()
|
||||
{
|
||||
$this->server->setProtocolVersion(4);
|
||||
$this->server->setProtocolVersion('4a');
|
||||
$this->server->setProtocolVersion(5);
|
||||
$this->server->setProtocolVersion(null);
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetInvalidProtocolVersion()
|
||||
{
|
||||
$this->server->setProtocolVersion(6);
|
||||
}
|
||||
|
||||
public function testSetAuthArray()
|
||||
{
|
||||
$this->server->setAuthArray(array());
|
||||
|
||||
$this->server->setAuthArray(array(
|
||||
'name1' => 'password1',
|
||||
'name2' => 'password2'
|
||||
));
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testSetAuthInvalid()
|
||||
{
|
||||
$this->server->setAuth(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testUnableToSetAuthIfProtocolDoesNotSupportAuth()
|
||||
{
|
||||
$this->server->setProtocolVersion(4);
|
||||
|
||||
$this->server->setAuthArray(array());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException UnexpectedValueException
|
||||
*/
|
||||
public function testUnableToSetProtocolWhichDoesNotSupportAuth()
|
||||
{
|
||||
$this->server->setAuthArray(array());
|
||||
|
||||
// this is okay
|
||||
$this->server->setProtocolVersion(5);
|
||||
|
||||
$this->server->setProtocolVersion(4);
|
||||
}
|
||||
|
||||
public function testConnectWillCreateConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80));
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testConnectWillCreateConnectionWithSourceUri()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('google.com:80?source=socks5%3A%2F%2F10.20.30.40%3A5060')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80, 'socks5://10.20.30.40:5060'));
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
}
|
||||
|
||||
public function testConnectWillRejectIfConnectionFails()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
|
||||
|
||||
$promise = new Promise(function ($_, $reject) { $reject(new \RuntimeException()); });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testConnectWillCancelConnectionIfStreamCloses()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { }, function () {
|
||||
throw new \RuntimeException();
|
||||
});
|
||||
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80));
|
||||
|
||||
$stream->emit('close');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testConnectWillAbortIfPromiseIsCanceled()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
|
||||
|
||||
$promise = new Promise(function () { }, function () {
|
||||
throw new \RuntimeException();
|
||||
});
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('google.com:80')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80));
|
||||
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function provideConnectionErrors()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
new RuntimeException('', SOCKET_EACCES),
|
||||
Server::ERROR_NOT_ALLOWED_BY_RULESET
|
||||
),
|
||||
array(
|
||||
new RuntimeException('', SOCKET_ENETUNREACH),
|
||||
Server::ERROR_NETWORK_UNREACHABLE
|
||||
),
|
||||
array(
|
||||
new RuntimeException('', SOCKET_EHOSTUNREACH),
|
||||
Server::ERROR_HOST_UNREACHABLE,
|
||||
),
|
||||
array(
|
||||
new RuntimeException('', SOCKET_ECONNREFUSED),
|
||||
Server::ERROR_CONNECTION_REFUSED
|
||||
),
|
||||
array(
|
||||
new RuntimeException('Connection refused'),
|
||||
Server::ERROR_CONNECTION_REFUSED
|
||||
),
|
||||
array(
|
||||
new RuntimeException('', SOCKET_ETIMEDOUT),
|
||||
Server::ERROR_TTL
|
||||
),
|
||||
array(
|
||||
new TimeoutException(1.0),
|
||||
Server::ERROR_TTL
|
||||
),
|
||||
array(
|
||||
new RuntimeException(),
|
||||
Server::ERROR_GENERAL
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideConnectionErrors
|
||||
* @param Exception $error
|
||||
* @param int $expectedCode
|
||||
*/
|
||||
public function testConnectWillReturnMappedSocks5ErrorCodeFromConnector($error, $expectedCode)
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
|
||||
|
||||
$promise = \React\Promise\reject($error);
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$promise = $this->server->connectTarget($stream, array('google.com', 80));
|
||||
|
||||
$code = null;
|
||||
$promise->then(null, function ($error) use (&$code) {
|
||||
$code = $error->getCode();
|
||||
});
|
||||
|
||||
$this->assertEquals($expectedCode, $code);
|
||||
}
|
||||
|
||||
public function testHandleSocksConnectionWillEndOnInvalidData()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
|
||||
$connection->expects($this->once())->method('pause');
|
||||
$connection->expects($this->once())->method('end');
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array('asdasdasdasdasd'));
|
||||
}
|
||||
|
||||
public function testHandleSocks4ConnectionWithIpv4WillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . pack('N', ip2long('127.0.0.1')) . "\x00"));
|
||||
}
|
||||
|
||||
public function testHandleSocks4aConnectionWithHostnameWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('example.com:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . "\x00\x00\x00\x01" . "\x00" . "example.com" . "\x00"));
|
||||
}
|
||||
|
||||
public function testHandleSocks4aConnectionWithHostnameAndSourceAddressWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'getRemoteAddress'))->getMock();
|
||||
$connection->expects($this->once())->method('getRemoteAddress')->willReturn('tcp://10.20.30.40:5060');
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('example.com:80?source=socks4%3A%2F%2F10.20.30.40%3A5060')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . "\x00\x00\x00\x01" . "\x00" . "example.com" . "\x00"));
|
||||
}
|
||||
|
||||
public function testHandleSocks4aConnectionWithSecureTlsSourceAddressWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'getRemoteAddress'))->getMock();
|
||||
$connection->expects($this->once())->method('getRemoteAddress')->willReturn('tls://10.20.30.40:5060');
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('example.com:80?source=socks4s%3A%2F%2F10.20.30.40%3A5060')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . "\x00\x00\x00\x01" . "\x00" . "example.com" . "\x00"));
|
||||
}
|
||||
|
||||
public function testHandleSocks4aConnectionWithInvalidHostnameWillNotEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
|
||||
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . "\x00\x00\x00\x01" . "\x00" . "tls://example.com:80?" . "\x00"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithIpv4WillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x01" . pack('N', ip2long('127.0.0.1')) . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithIpv4AndSourceAddressWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write', 'getRemoteAddress'))->getMock();
|
||||
$connection->expects($this->once())->method('getRemoteAddress')->willReturn('tcp://10.20.30.40:5060');
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80?source=socks5%3A%2F%2F10.20.30.40%3A5060')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x01" . pack('N', ip2long('127.0.0.1')) . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithSecureTlsIpv4AndSourceAddressWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write', 'getRemoteAddress'))->getMock();
|
||||
$connection->expects($this->once())->method('getRemoteAddress')->willReturn('tls://10.20.30.40:5060');
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80?source=socks5s%3A%2F%2F10.20.30.40%3A5060')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x01" . pack('N', ip2long('127.0.0.1')) . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithIpv6WillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('[::1]:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x04" . inet_pton('::1') . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithHostnameWillEstablishOutgoingConnection()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { });
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('example.com:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x03\x0B" . "example.com" . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithConnectorRefusedWillReturnReturnRefusedError()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\reject(new RuntimeException('Connection refused'));
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('example.com:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->expects($this->exactly(2))->method('write')->withConsecutive(array("\x05\x00"), array("\x05\x05" . "\x00\x01\x00\x00\x00\x00\x00\x00"));
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x03\x0B" . "example.com" . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5UdpCommandWillNotEstablishOutgoingConnectionAndReturnCommandError()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->expects($this->exactly(2))->method('write')->withConsecutive(array("\x05\x00"), array("\x05\x07" . "\x00\x01\x00\x00\x00\x00\x00\x00"));
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x03\x00\x03\x0B" . "example.com" . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocks5ConnectionWithInvalidHostnameWillNotEstablishOutgoingConnectionAndReturnGeneralError()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end', 'write'))->getMock();
|
||||
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->expects($this->exactly(2))->method('write')->withConsecutive(array("\x05\x00"), array("\x05\x01" . "\x00\x01\x00\x00\x00\x00\x00\x00"));
|
||||
|
||||
$connection->emit('data', array("\x05\x01\x00" . "\x05\x01\x00\x03\x15" . "tls://example.com:80?" . "\x00\x50"));
|
||||
}
|
||||
|
||||
public function testHandleSocksConnectionWillCancelOutputConnectionIfIncomingCloses()
|
||||
{
|
||||
$connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('pause', 'end'))->getMock();
|
||||
|
||||
$promise = new Promise(function () { }, $this->expectCallableOnce());
|
||||
|
||||
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise);
|
||||
|
||||
$this->server->onConnection($connection);
|
||||
|
||||
$connection->emit('data', array("\x04\x01" . "\x00\x50" . pack('N', ip2long('127.0.0.1')) . "\x00"));
|
||||
$connection->emit('close');
|
||||
}
|
||||
|
||||
public function testUnsetAuth()
|
||||
{
|
||||
$this->server->unsetAuth();
|
||||
$this->server->unsetAuth();
|
||||
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
82
vendor/clue/socks-react/tests/StreamReaderTest.php
vendored
Executable file
82
vendor/clue/socks-react/tests/StreamReaderTest.php
vendored
Executable file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
use Clue\React\Socks\StreamReader;
|
||||
|
||||
class StreamReaderTest extends TestCase
|
||||
{
|
||||
private $reader;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->reader = new StreamReader();
|
||||
}
|
||||
|
||||
public function testReadByteAssertCorrect()
|
||||
{
|
||||
$this->reader->readByteAssert(0x01)->then($this->expectCallableOnce(0x01));
|
||||
|
||||
$this->reader->write("\x01");
|
||||
}
|
||||
|
||||
public function testReadByteAssertInvalid()
|
||||
{
|
||||
$this->reader->readByteAssert(0x02)->then(null, $this->expectCallableOnce());
|
||||
|
||||
$this->reader->write("\x03");
|
||||
}
|
||||
|
||||
public function testReadStringNull()
|
||||
{
|
||||
$this->reader->readStringNull()->then($this->expectCallableOnce('hello'));
|
||||
|
||||
$this->reader->write("hello\x00");
|
||||
}
|
||||
|
||||
public function testReadStringLength()
|
||||
{
|
||||
$this->reader->readLength(5)->then($this->expectCallableOnce('hello'));
|
||||
|
||||
$this->reader->write('he');
|
||||
$this->reader->write('ll');
|
||||
$this->reader->write('o ');
|
||||
|
||||
$this->assertEquals(' ', $this->reader->getBuffer());
|
||||
}
|
||||
|
||||
public function testReadBuffered()
|
||||
{
|
||||
$this->reader->write('hello');
|
||||
|
||||
$this->reader->readLength(5)->then($this->expectCallableOnce('hello'));
|
||||
|
||||
$this->assertEquals('', $this->reader->getBuffer());
|
||||
}
|
||||
|
||||
public function testSequence()
|
||||
{
|
||||
$this->reader->readByte()->then($this->expectCallableOnce(ord('h')));
|
||||
$this->reader->readByteAssert(ord('e'))->then($this->expectCallableOnce(ord('e')));
|
||||
$this->reader->readLength(4)->then($this->expectCallableOnce('llo '));
|
||||
$this->reader->readBinary(array('w'=>'C', 'o' => 'C'))->then($this->expectCallableOnce(array('w' => ord('w'), 'o' => ord('o'))));
|
||||
|
||||
$this->reader->write('hello world');
|
||||
|
||||
$this->assertEquals('rld', $this->reader->getBuffer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidStructure()
|
||||
{
|
||||
$this->reader->readBinary(array('invalid' => 'y'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidCallback()
|
||||
{
|
||||
$this->reader->readBufferCallback(array());
|
||||
}
|
||||
}
|
||||
103
vendor/clue/socks-react/tests/bootstrap.php
vendored
Executable file
103
vendor/clue/socks-react/tests/bootstrap.php
vendored
Executable file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
(include_once __DIR__.'/../vendor/autoload.php') OR die(PHP_EOL.'ERROR: composer autoloader not found, run "composer install" or see README for instructions'.PHP_EOL);
|
||||
|
||||
class TestCase extends PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected function expectCallableOnce()
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
|
||||
|
||||
if (func_num_args() > 0) {
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->equalTo(func_get_arg(0)));
|
||||
} else {
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke');
|
||||
}
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableNever()
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->never())
|
||||
->method('__invoke');
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableOnceWithExceptionCode($code)
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->callback(function ($e) use ($code) {
|
||||
return $e->getCode() === $code;
|
||||
}));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableOnceParameter($type)
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->isInstanceOf($type));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://github.com/reactphp/react/blob/master/tests/React/Tests/Socket/TestCase.php (taken from reactphp/react)
|
||||
*/
|
||||
protected function createCallableMock()
|
||||
{
|
||||
return $this->getMockBuilder('CallableStub')->getMock();
|
||||
}
|
||||
|
||||
protected function expectPromiseResolve($promise)
|
||||
{
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
|
||||
$that = $this;
|
||||
$promise->then(null, function($error) use ($that) {
|
||||
$that->assertNull($error);
|
||||
$that->fail('promise rejected');
|
||||
});
|
||||
$promise->then($this->expectCallableOnce(), $this->expectCallableNever());
|
||||
|
||||
return $promise;
|
||||
}
|
||||
|
||||
protected function expectPromiseReject($promise)
|
||||
{
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
|
||||
$that = $this;
|
||||
$promise->then(function($value) use ($that) {
|
||||
$that->assertNull($value);
|
||||
$that->fail('promise resolved');
|
||||
});
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnce());
|
||||
|
||||
return $promise;
|
||||
}
|
||||
}
|
||||
|
||||
class CallableStub
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user