Skip to content

Commit fb865eb

Browse files
committed
Merge pull request #11 from clue/tests
Tests
2 parents 6538eb9 + 689ea3b commit fb865eb

9 files changed

Lines changed: 341 additions & 138 deletions

File tree

examples/client.php

Lines changed: 13 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,31 @@
11
<?php
22

3-
use ConnectionManager\SecureConnectionManager;
4-
use React\Promise\PromiseInterface;
53
use React\Stream\Stream;
64
use Clue\React\Socks\Client;
75

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

8+
$port = isset($argv[1]) ? $argv[1] : 9050;
9+
1010
$loop = React\EventLoop\Factory::create();
1111

12-
$client = new Client($loop, '127.0.0.1', 9051);
12+
$client = new Client($loop, '127.0.0.1', $port);
1313
$client->setTimeout(3.0);
1414
$client->setResolveLocal(false);
15-
//$client->setProtocolVersion(5);
15+
// $client->setProtocolVersion(5);
1616
// $client->setAuth('test','test');
1717

18-
echo 'Demo SOCKS client connecting to SOCKS server 127.0.0.1:9051' . PHP_EOL;
19-
20-
function ex(Exception $exception=null)
21-
{
22-
if ($exception !== null) {
23-
echo 'message: ' . $exception->getMessage() . PHP_EOL;
24-
while (($exception = $exception->getPrevious())) {
25-
echo 'previous: ' . $exception->getMessage() . PHP_EOL;
26-
}
27-
}
28-
}
29-
30-
function assertFail(PromiseInterface $promise, $name='end')
31-
{
32-
return $promise->then(
33-
function (Stream $stream) use ($name) {
34-
echo 'FAIL: connection to '.$name.' OK' . PHP_EOL;
35-
$stream->close();
36-
},
37-
function (Exception $error) use ($name) {
38-
39-
echo 'EXPECTED: connection to '.$name.' failed: ';
40-
ex($error);
41-
}
42-
);
43-
}
44-
45-
function assertOkay(PromiseInterface $promise, $name='end')
46-
{
47-
return $promise->then(
48-
function ($stream) use ($name) {
49-
echo 'EXPECTED: connection to '.$name.' OK' . PHP_EOL;
50-
$stream->close();
51-
},
52-
function (Exception $error) use ($name) {
53-
echo 'FAIL: connection to '.$name.' failed: ';
54-
ex($error);
55-
}
56-
);
57-
}
18+
echo 'Demo SOCKS client connecting to SOCKS server 127.0.0.1:' . $port . PHP_EOL;
19+
echo 'Not already running a SOCKS server? Try this: ssh -D ' . $port . ' localhost' . PHP_EOL;
5820

5921
$tcp = $client->createConnector();
6022

61-
assertOkay($tcp->create('www.google.com', 80), 'www.google.com:80');
62-
63-
assertFail($tcp->create('www.google.commm', 80), 'www.google.commm:80');
64-
65-
assertFail($tcp->create('www.google.com', 8080), 'www.google.com:8080');
66-
67-
$ssl = $client->createSecureConnector();
68-
69-
assertOkay($ssl->create('www.google.com', 443), 'ssl://www.google.com:443');
70-
71-
assertFail($ssl->create('www.google.com', 80), 'ssl://www.google.com:80');
72-
73-
assertFail($ssl->create('www.google.com', 8080), 'ssl://www.google.com:8080');
74-
75-
// $ssl->getConnection('127.0.0.1','443')->then(function (React\Stream $stream) {
76-
// echo 'connected';
77-
// $stream->write("GET / HTTP/1.0\r\n\r\n");
78-
// $stream->on('data', function ($data) {
79-
// echo $data;
80-
// });
81-
// });
82-
83-
$loop->addTimer(8, function() use ($loop) {
84-
$loop->stop();
85-
echo 'STOP - stopping mainloop after 8 seconds' . PHP_EOL;
86-
});
23+
$tcp->create('www.google.com', 80)->then(function (Stream $stream) {
24+
echo 'connected' . PHP_EOL;
25+
$stream->write("GET / HTTP/1.0\r\n\r\n");
26+
$stream->on('data', function ($data) {
27+
echo $data;
28+
});
29+
}, 'var_dump');
8730

8831
$loop->run();

examples/server-auth.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use Clue\React\Socks\Server;
4+
use React\Socket\Server as Socket;
5+
6+
include_once __DIR__.'/../vendor/autoload.php';
7+
8+
$port = isset($argv[1]) ? $argv[1] : 9050;
9+
10+
$loop = React\EventLoop\Factory::create();
11+
12+
// listen on localhost:$port
13+
$socket = new Socket($loop);
14+
$socket->listen($port,'localhost');
15+
16+
// start a new server listening for incoming connection on the given socket
17+
// require authentication and hence make this a SOCKS5-only server
18+
$server = new Server($loop, $socket);
19+
$server->setAuthArray(array(
20+
'tom' => 'god',
21+
'user' => 'p@ssw0rd'
22+
));
23+
24+
echo 'SOCKS5 server requiring authentication listening on localhost:' . $port . PHP_EOL;
25+
26+
$loop->run();

examples/server-middleman.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,27 @@
22

33
use Clue\React\Socks\Client;
44
use Clue\React\Socks\Server;
5+
use React\Socket\Server as Socket;
6+
57
include_once __DIR__.'/../vendor/autoload.php';
68

9+
$myPort = isset($argv[1]) ? $argv[1] : 9051;
10+
$otherPort = isset($argv[2]) ? $argv[2] : 9050;
11+
712
$loop = React\EventLoop\Factory::create();
813

9-
// set next SOCKS server as target
10-
$target = new Client($loop, '127.0.0.1',9050);
14+
// set next SOCKS server localhost:$otherPort as target
15+
$target = new Client($loop, '127.0.0.1', $otherPort);
1116
$target->setAuth('user','p@ssw0rd');
1217

13-
// start a new server which forwards all connections to another SOCKS server
14-
$socket = new React\Socket\Server($loop);
15-
$socket->listen(9051, 'localhost');
18+
// listen on localhost:$myPort
19+
$socket = new Socket($loop);
20+
$socket->listen($myPort, 'localhost');
1621

22+
// start a new server which forwards all connections to the other SOCKS server
1723
$server = new Server($loop, $socket, $target->createConnector());
1824

19-
echo 'SOCKS server listening on localhost:9051 (which forwards everything to SOCKS server 127.0.0.1:9050)' . PHP_EOL;
25+
echo 'SOCKS server listening on localhost:' . $myPort . ' (which forwards everything to target SOCKS server 127.0.0.1:' . $otherPort . ')' . PHP_EOL;
26+
echo 'Not already running the target SOCKS server? Try this: php server-auth.php ' . $otherPort . PHP_EOL;
2027

2128
$loop->run();

examples/server.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
<?php
22

33
use Clue\React\Socks\Server;
4+
use React\Socket\Server as Socket;
5+
46
include_once __DIR__.'/../vendor/autoload.php';
57

8+
$port = isset($argv[1]) ? $argv[1] : 9050;
9+
610
$loop = React\EventLoop\Factory::create();
711

8-
$socket = new React\Socket\Server($loop);
9-
$socket->listen('9050','localhost');
12+
// listen on localhost:$port
13+
$socket = new Socket($loop);
14+
$socket->listen($port,'localhost');
1015

16+
// start a new server listening for incoming connection on the given socket
1117
$server = new Server($loop, $socket);
12-
$server->setAuthArray(array(
13-
'tom' => 'god',
14-
'user' => 'p@ssw0rd'
15-
));
1618

17-
echo 'SOCKS server listening on localhost:9050' . PHP_EOL;
19+
echo 'SOCKS server listening on localhost:' . $port . PHP_EOL;
1820

1921
$loop->run();
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use Clue\React\Socks\Client;
44

5-
class ClientApiTest extends TestCase
5+
class ClientTest extends TestCase
66
{
77
/** @var Client */
88
private $client;

tests/FunctionalTest.php

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
<?php
2+
3+
use React\Stream\Stream;
4+
use Clue\React\Socks\Client;
5+
use Clue\React\Socks\Server;
6+
use React\Promise\PromiseInterface;
7+
8+
class FunctionalTest extends TestCase
9+
{
10+
private $loop;
11+
private $client;
12+
private $server;
13+
14+
public function setUp()
15+
{
16+
$this->loop = React\EventLoop\Factory::create();
17+
18+
$socket = $this->createSocketServer();
19+
$port = $socket->getPort();
20+
$this->assertNotEquals(0, $port);
21+
22+
$this->server = new Server($this->loop, $socket);
23+
$this->client = new Client($this->loop, '127.0.0.1', $port);
24+
}
25+
26+
public function testConnection()
27+
{
28+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
29+
}
30+
31+
public function testConnectionSocks4()
32+
{
33+
$this->server->setProtocolVersion(4);
34+
$this->client->setProtocolVersion(4);
35+
36+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
37+
}
38+
39+
public function testConnectionSocks5()
40+
{
41+
$this->server->setProtocolVersion(5);
42+
$this->client->setProtocolVersion(5);
43+
44+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
45+
}
46+
47+
public function testConnectionInvalidSocks4aRemote()
48+
{
49+
$this->client->setProtocolVersion('4a');
50+
$this->client->setResolveLocal(false);
51+
52+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
53+
}
54+
55+
public function testConnectionSocks5Remote()
56+
{
57+
$this->client->setProtocolVersion(5);
58+
$this->client->setResolveLocal(false);
59+
60+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
61+
}
62+
63+
public function testConnectionAuthentication()
64+
{
65+
$this->server->setAuthArray(array('name' => 'pass'));
66+
$this->client->setAuth('name', 'pass');
67+
68+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
69+
}
70+
71+
public function testConnectionAuthenticationUnused()
72+
{
73+
$this->client->setAuth('name', 'pass');
74+
75+
$this->assertResolveStream($this->client->getConnection('www.google.com', 80));
76+
}
77+
78+
public function testConnectionInvalidProtocolMismatch()
79+
{
80+
$this->server->setProtocolVersion(5);
81+
$this->client->setProtocolVersion(4);
82+
83+
$this->assertRejectPromise($this->client->getConnection('www.google.com', 80));
84+
}
85+
86+
public function testConnectionInvalidNoAuthentication()
87+
{
88+
$this->server->setAuthArray(array('name' => 'pass'));
89+
$this->client->setProtocolVersion(5);
90+
91+
$this->assertRejectPromise($this->client->getConnection('www.google.com', 80));
92+
}
93+
94+
public function testConnectionInvalidAuthenticationMismatch()
95+
{
96+
$this->server->setAuthArray(array('name' => 'pass'));
97+
$this->client->setAuth('user', 'other');
98+
99+
$this->assertRejectPromise($this->client->getConnection('www.google.com', 80));
100+
}
101+
102+
public function testConnectorOkay()
103+
{
104+
$tcp = $this->client->createConnector();
105+
106+
$this->assertResolveStream($tcp->create('www.google.com', 80));
107+
}
108+
109+
public function testConnectorInvalidDomain()
110+
{
111+
$tcp = $this->client->createConnector();
112+
113+
$this->assertRejectPromise($tcp->create('www.google.commm', 80));
114+
}
115+
116+
public function testConnectorInvalidUnboundPortTimeout()
117+
{
118+
$this->client->setTimeout(0.1);
119+
$tcp = $this->client->createConnector();
120+
121+
$this->assertRejectPromise($tcp->create('www.google.com', 8080));
122+
}
123+
124+
public function testSecureConnectorOkay()
125+
{
126+
$ssl = $this->client->createSecureConnector();
127+
128+
$this->assertResolveStream($ssl->create('www.google.com', 443));
129+
}
130+
131+
public function testSecureConnectorInvalidPlaintextIsNotSsl()
132+
{
133+
$ssl = $this->client->createSecureConnector();
134+
135+
$this->assertRejectPromise($ssl->create('www.google.com', 80));
136+
}
137+
138+
public function testSecureConnectorInvalidUnboundPortTimeout()
139+
{
140+
$this->client->setTimeout(0.1);
141+
$ssl = $this->client->createSecureConnector();
142+
143+
$this->assertRejectPromise($ssl->create('www.google.com', 8080));
144+
}
145+
146+
private function createSocketServer()
147+
{
148+
$socket = new React\Socket\Server($this->loop);
149+
$socket->listen(0);
150+
151+
return $socket;
152+
}
153+
154+
private function assertResolveStream($promise)
155+
{
156+
$this->expectPromiseResolve($promise);
157+
158+
$promise->then(function ($stream) {
159+
$stream->close();
160+
});
161+
162+
$this->waitFor($promise);
163+
}
164+
165+
private function assertRejectPromise($promise)
166+
{
167+
$this->expectPromiseReject($promise);
168+
169+
$this->setExpectedException('Exception');
170+
$this->waitFor($promise);
171+
}
172+
173+
private function waitFor(PromiseInterface $promise)
174+
{
175+
$resolved = null;
176+
$exception = null;
177+
178+
$promise->then(function ($c) use (&$resolved) {
179+
$resolved = $c;
180+
}, function($error) use (&$exception) {
181+
$exception = $error;
182+
});
183+
184+
while ($resolved === null && $exception === null) {
185+
$this->loop->tick();
186+
}
187+
188+
if ($exception !== null) {
189+
throw $exception;
190+
}
191+
192+
return $resolved;
193+
}
194+
}

0 commit comments

Comments
 (0)