Skip to content

Commit 21df009

Browse files
committed
Use ECONNRESET and EIO error codes for connection issues
1 parent 0cac961 commit 21df009

2 files changed

Lines changed: 46 additions & 13 deletions

File tree

src/Client.php

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ public function handleConnectedSocks(ConnectionInterface $stream, $host, $port)
185185
$reader = new StreamReader();
186186
$stream->on('data', array($reader, 'write'));
187187

188+
$stream->on('error', $onError = function (Exception $e) use ($deferred) {
189+
$deferred->reject(new RuntimeException('Stream error while waiting for response from proxy (EIO)', defined('SOCKET_EIO') ? SOCKET_EIO : 5, $e));
190+
});
191+
192+
$stream->on('close', $onClose = function () use ($deferred) {
193+
$deferred->reject(new RuntimeException('Connection to proxy lost while waiting for response (ECONNRESET)', defined('SOCKET_ECONNRESET') ? SOCKET_ECONNRESET : 104));
194+
});
195+
188196
if ($this->protocolVersion === '5') {
189197
$promise = $this->handleSocks5($stream, $host, $port, $reader);
190198
} else {
@@ -196,26 +204,21 @@ public function handleConnectedSocks(ConnectionInterface $stream, $host, $port)
196204
$deferred->reject(new Exception('Unable to communicate...', 0, $error));
197205
});
198206

199-
$deferred->promise()->then(
200-
function (ConnectionInterface $stream) use ($reader) {
201-
$stream->removeAllListeners('end');
202-
207+
return $deferred->promise()->then(
208+
function (ConnectionInterface $stream) use ($reader, $onError, $onClose) {
203209
$stream->removeListener('data', array($reader, 'write'));
210+
$stream->removeListener('error', $onError);
211+
$stream->removeListener('close', $onClose);
204212

205213
return $stream;
206214
},
207-
function ($error) use ($stream) {
215+
function ($error) use ($stream, $onClose) {
216+
$stream->removeListener('close', $onClose);
208217
$stream->close();
209218

210-
return $error;
219+
throw $error;
211220
}
212221
);
213-
214-
$stream->on('end', function () use ($stream, $deferred) {
215-
$deferred->reject(new Exception('Premature end while establishing socks session'));
216-
});
217-
218-
return $deferred->promise();
219222
}
220223

221224
private function handleSocks4(ConnectionInterface $stream, $host, $port, StreamReader $reader)

tests/ClientTest.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public function testCreateWithInvalidPortDoesNotConnect()
122122

123123
public function testConnectorRejectsWillRejectConnection()
124124
{
125-
$promise = \React\Promise\Reject(new RuntimeException());
125+
$promise = \React\Promise\reject(new RuntimeException());
126126

127127
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
128128

@@ -159,4 +159,34 @@ public function testCancelConnectionDuringSessionWillCloseStream()
159159

160160
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNABORTED));
161161
}
162+
163+
public function testEmitConnectionCloseDuringSessionWillRejectConnection()
164+
{
165+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
166+
167+
$promise = \React\Promise\resolve($stream);
168+
169+
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
170+
171+
$promise = $this->client->connect('google.com:80');
172+
173+
$stream->emit('close');
174+
175+
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNRESET));
176+
}
177+
178+
public function testEmitConnectionErrorDuringSessionWillRejectConnection()
179+
{
180+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('write', 'close'))->getMock();
181+
182+
$promise = \React\Promise\resolve($stream);
183+
184+
$this->connector->expects($this->once())->method('connect')->with('127.0.0.1:1080?hostname=google.com')->willReturn($promise);
185+
186+
$promise = $this->client->connect('google.com:80');
187+
188+
$stream->emit('error', array(new RuntimeException()));
189+
190+
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EIO));
191+
}
162192
}

0 commit comments

Comments
 (0)