Skip to content

Commit

Permalink
Remove error_get_last calls
Browse files Browse the repository at this point in the history
  • Loading branch information
kelunik committed Jun 24, 2020
1 parent f78ec36 commit 75321ab
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 33 deletions.
23 changes: 17 additions & 6 deletions src/DatagramSocket.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public static function bind(string $uri, ?BindContext $context = null): self

return new self($server, $context->getChunkSize());
}

/** @var resource|null UDP socket resource. */
private $socket;
/** @var string Watcher ID. */
Expand Down Expand Up @@ -155,12 +156,22 @@ public function send(SocketAddress $address, string $data): Promise
return new Failure(new SocketException('The endpoint is not writable'));
}

$result = @\stream_socket_sendto($this->socket, $data, 0, $address->toString());

/** @psalm-suppress TypeDoesNotContainType */
if ($result < 0 || $result === false) {
$error = \error_get_last()['message'] ?? 'Unknown error';
return new Failure(new SocketException('Could not send packet on endpoint: ' . $error));
try {
try {
\set_error_handler(static function (int $errno, string $errstr) {
throw new SocketException(\sprintf('Could not send packet on endpoint: %s', $errstr));
});

$result = @\stream_socket_sendto($this->socket, $data, 0, $address->toString());
/** @psalm-suppress TypeDoesNotContainType */
if ($result < 0 || $result === false) {
throw new SocketException('Could not send packet on endpoint: Unknown error');
}
} finally {
\restore_error_handler();
}
} catch (SocketException $e) {
return new Failure($e);
}

return new Success($result);
Expand Down
56 changes: 40 additions & 16 deletions src/Internal/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,28 @@ function setupTls($socket, array $options, ?CancellationToken $cancellationToken

\error_clear_last();
\stream_context_set_option($socket, $options);
$result = @\stream_socket_enable_crypto($socket, $enable = true);

try {
\set_error_handler(static function (int $errno, string $errstr) {
new TlsException('TLS negotiation failed: ' . $errstr);
});

$result = @\stream_socket_enable_crypto($socket, $enable = true);
if ($result === false) {
throw new TlsException('TLS negotiation failed: Unknown error');
}
} catch (TlsException $e) {
return new Failure($e);
} finally {
\restore_error_handler();
}

// Yes, that function can return true / false / 0, don't use weak comparisons.
if ($result === true) {
/** @psalm-suppress InvalidReturnStatement */
return new Success;
}

if ($result === false) {
return new Failure(new TlsException(
'TLS negotiation failed: ' . (\error_get_last()['message'] ?? 'Unknown error')
));
}

return call(static function () use ($socket, $cancellationToken) {
$cancellationToken->throwIfRequested();

Expand All @@ -116,21 +124,37 @@ function setupTls($socket, array $options, ?CancellationToken $cancellationToken
$cancellationToken,
$id
) {
\error_clear_last();
$result = @\stream_socket_enable_crypto($socket, true);
$lastError = \error_get_last();
try {
try {
\set_error_handler(static function (int $errno, string $errstr) use ($socket) {
if (\feof($socket)) {
$errstr = 'Connection reset by peer';
}

throw new TlsException('TLS negotiation failed: ' . $errstr);
});

$result = @\stream_socket_enable_crypto($socket, true);
if ($result === false) {
$message = \feof($socket) ? 'Connection reset by peer' : 'Unknown error';
throw new TlsException('TLS negotiation failed: ' . $message);
}
} finally {
\restore_error_handler();
}
} catch (TlsException $e) {
Loop::cancel($watcher);
$cancellationToken->unsubscribe($id);
$deferred->fail($e);

return;
}

// If $result is 0, just wait for the next invocation
if ($result === true) {
Loop::cancel($watcher);
$cancellationToken->unsubscribe($id);
$deferred->resolve();
} elseif ($result === false) {
Loop::cancel($watcher);
$cancellationToken->unsubscribe($id);
$deferred->fail(new TlsException('TLS negotiation failed: ' . (\feof($socket)
? 'Connection reset by peer'
: ($lastError['message'] ?? 'Unknown error'))));
}
}, $deferred);

Expand Down
26 changes: 15 additions & 11 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@
const LOOP_CONNECTOR_IDENTIFIER = Connector::class;

/**
* @deprecated Use Server::listen() instead.
*
* Listen for client connections on the specified server address.
*
* If you want to accept TLS connections, you have to use `yield $socket->setupTls()` after accepting new clients.
*
* @see Server::listen()
*
* @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
* @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
* @param BindContext|null $context Context options for listening.
*
* @return Server
*
* @throws SocketException If binding to the specified URI failed.
* @throws \Error If an invalid scheme is given.
* @see Server::listen()
*
* @deprecated Use Server::listen() instead.
*/
function listen(string $uri, ?BindContext $context = null): Server
{
Expand Down Expand Up @@ -56,7 +55,7 @@ function connector(Connector $connector = null): Connector
/**
* Asynchronously establish a socket connection to the specified URI.
*
* @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
* @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
* @param ConnectContext $context Socket connect context to use when connecting.
* @param CancellationToken|null $token
*
Expand All @@ -79,12 +78,17 @@ function connect(string $uri, ConnectContext $context = null, CancellationToken
*/
function createPair(): array
{
if (($sockets = @\stream_socket_pair(\stripos(PHP_OS, 'win') === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP)) === false) {
$message = 'Failed to create socket pair.';
if ($error = \error_get_last()) {
$message .= \sprintf(' Errno: %d; %s', $error['type'], $error['message']);
try {
\set_error_handler(static function (int $errno, string $errstr) {
throw new SocketException(\sprintf('Failed to create socket pair. Errno: %d; %s', $errno, $errstr));
});

$sockets = @\stream_socket_pair(\stripos(PHP_OS, 'win') === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);

This comment has been minimized.

Copy link
@nicolas-grekas

nicolas-grekas Jun 25, 2020

Contributor

No need for the @ in this patch.

This comment has been minimized.

Copy link
@kelunik

kelunik Jun 25, 2020

Author Member

Indeed, dropped: b9064b9

if ($sockets === false) {
throw new SocketException('Failed to create socket pair.');
}
throw new SocketException($message);
} finally {
\restore_error_handler();
}

return [ResourceSocket::fromClientSocket($sockets[0]), ResourceSocket::fromClientSocket($sockets[1])];
Expand Down

0 comments on commit 75321ab

Please sign in to comment.