2020-02-14 20:31:11 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Amp\Ipc;
|
|
|
|
|
|
|
|
use Amp\Ipc\Sync\ChannelledSocket;
|
|
|
|
use Amp\Promise;
|
|
|
|
|
|
|
|
use function Amp\call;
|
|
|
|
|
2020-07-17 14:37:37 +02:00
|
|
|
/**
|
|
|
|
* Create IPC server.
|
|
|
|
*
|
|
|
|
* @param string $uri Local endpoint on which to listen for requests
|
|
|
|
*
|
|
|
|
* @return IpcServer
|
|
|
|
*/
|
|
|
|
function listen(string $uri): IpcServer
|
|
|
|
{
|
|
|
|
return new IpcServer($uri);
|
|
|
|
}
|
2020-09-24 21:00:49 +02:00
|
|
|
|
2020-02-14 20:31:11 +01:00
|
|
|
/**
|
|
|
|
* Connect to IPC server.
|
|
|
|
*
|
|
|
|
* @param string $uri URI
|
|
|
|
*
|
|
|
|
* @return Promise<ChannelledSocket>
|
|
|
|
*/
|
|
|
|
function connect(string $uri): Promise
|
|
|
|
{
|
|
|
|
return call(static function () use ($uri) {
|
2020-03-05 21:16:53 +01:00
|
|
|
if (!\file_exists($uri)) {
|
2020-03-05 21:12:35 +01:00
|
|
|
throw new \RuntimeException("The endpoint does not exist!");
|
|
|
|
}
|
2020-03-05 21:16:53 +01:00
|
|
|
|
2020-02-14 20:31:11 +01:00
|
|
|
$type = \filetype($uri);
|
2020-03-05 21:12:35 +01:00
|
|
|
if ($type !== 'fifo') {
|
|
|
|
if ($type === 'file') {
|
|
|
|
$uri = \file_get_contents($uri);
|
|
|
|
} else {
|
|
|
|
$uri = "unix://$uri";
|
2020-02-14 20:31:11 +01:00
|
|
|
}
|
2020-03-05 21:12:35 +01:00
|
|
|
if (!$socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT)) {
|
|
|
|
$message = "Could not connect to IPC socket";
|
|
|
|
if ($error = \error_get_last()) {
|
|
|
|
$message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
|
|
|
|
}
|
|
|
|
throw new \RuntimeException($message);
|
|
|
|
}
|
|
|
|
return new ChannelledSocket($socket, $socket);
|
|
|
|
}
|
2020-02-14 20:31:11 +01:00
|
|
|
|
2020-03-05 21:12:35 +01:00
|
|
|
$suffix = \bin2hex(\random_bytes(10));
|
|
|
|
$prefix = \sys_get_temp_dir()."/amp-".$suffix.".fifo";
|
|
|
|
|
|
|
|
if (\strlen($prefix) > 0xFFFF) {
|
|
|
|
throw new \RuntimeException('Prefix is too long!');
|
|
|
|
}
|
|
|
|
|
|
|
|
$sockets = [
|
2021-05-06 22:01:25 +02:00
|
|
|
$prefix."2",
|
|
|
|
$prefix."1",
|
|
|
|
];
|
2020-02-14 20:31:11 +01:00
|
|
|
|
2020-03-05 21:12:35 +01:00
|
|
|
foreach ($sockets as $k => &$socket) {
|
|
|
|
if (!\posix_mkfifo($socket, 0777)) {
|
|
|
|
throw new \RuntimeException('Could not create FIFO client socket!');
|
2020-02-14 20:31:11 +01:00
|
|
|
}
|
|
|
|
|
2020-03-05 21:12:35 +01:00
|
|
|
\register_shutdown_function(static function () use ($socket): void {
|
|
|
|
@\unlink($socket);
|
|
|
|
});
|
2020-02-14 20:31:11 +01:00
|
|
|
|
2020-03-05 21:12:35 +01:00
|
|
|
if (!$socket = \fopen($socket, 'r+')) { // Open in r+w mode to prevent blocking if there is no reader
|
|
|
|
throw new \RuntimeException("Could not open FIFO client socket");
|
2020-02-14 20:31:11 +01:00
|
|
|
}
|
|
|
|
}
|
2020-03-05 21:12:35 +01:00
|
|
|
|
|
|
|
if (!$tempSocket = \fopen($uri, 'r+')) { // Open in r+w mode to prevent blocking if there is no reader
|
|
|
|
throw new \RuntimeException("Could not connect to FIFO server");
|
2020-02-14 20:31:11 +01:00
|
|
|
}
|
2020-03-05 21:12:35 +01:00
|
|
|
\stream_set_blocking($tempSocket, false);
|
|
|
|
\stream_set_write_buffer($tempSocket, 0);
|
|
|
|
|
|
|
|
if (!\fwrite($tempSocket, \pack('v', \strlen($prefix)).$prefix)) {
|
2021-05-06 22:01:25 +02:00
|
|
|
\fclose($tempSocket);
|
|
|
|
$tempSocket = null;
|
2020-03-05 21:12:35 +01:00
|
|
|
throw new \RuntimeException("Failure sending request to FIFO server");
|
2020-02-14 20:31:11 +01:00
|
|
|
}
|
2020-03-05 21:12:35 +01:00
|
|
|
\fclose($tempSocket);
|
|
|
|
$tempSocket = null;
|
|
|
|
|
|
|
|
return new ChannelledSocket(...$sockets);
|
2020-02-14 20:31:11 +01:00
|
|
|
});
|
|
|
|
}
|