public function loadEtcResolvConf($filename) { if (!file_exists($filename)) { return When::reject(new \InvalidArgumentException("The filename for /etc/resolv.conf given does not exist: {$filename}")); } try { $deferred = new Deferred(); $fd = fopen($filename, 'r'); stream_set_blocking($fd, 0); $contents = ''; $stream = new Stream($fd, $this->loop); $stream->on('data', function ($data) use(&$contents) { $contents .= $data; }); $stream->on('end', function () use(&$contents, $deferred) { $deferred->resolve($contents); }); $stream->on('error', function ($error) use($deferred) { $deferred->reject($error); }); return $deferred->promise(); } catch (\Exception $e) { return When::reject($e); } }
public function write($data) { if (!$this->in->isWritable()) { throw new \Exception('Stream not writable'); } $this->in->write($data); }
public function __construct(Stream $stream, ParserInterface $parser = null, SerializerInterface $serializer = null) { if ($parser === null || $serializer === null) { $factory = new ProtocolFactory(); if ($parser === null) { $parser = $factory->createResponseParser(); } if ($serializer === null) { $serializer = $factory->createSerializer(); } } $that = $this; $stream->on('data', function ($chunk) use($parser, $that) { try { $models = $parser->pushIncoming($chunk); } catch (ParserException $error) { $that->emit('error', array($error)); $that->close(); return; } foreach ($models as $data) { try { $that->handleMessage($data); } catch (UnderflowException $error) { $that->emit('error', array($error)); $that->close(); return; } } }); $stream->on('close', array($this, 'close')); $this->stream = $stream; $this->parser = $parser; $this->serializer = $serializer; }
/** * @dataProvider loopProvider */ public function testBufferReadsLargeChunks($condition, $loopFactory) { if (true !== $condition()) { return $this->markTestSkipped('Loop implementation not available'); } $loop = $loopFactory(); list($sockA, $sockB) = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0); $streamA = new Stream($sockA, $loop); $streamB = new Stream($sockB, $loop); $bufferSize = 4096; $streamA->bufferSize = $bufferSize; $streamB->bufferSize = $bufferSize; $testString = str_repeat("*", $streamA->bufferSize + 1); $buffer = ""; $streamB->on('data', function ($data, $streamB) use(&$buffer, &$testString) { $buffer .= $data; }); $streamA->write($testString); $loop->tick(); $loop->tick(); $loop->tick(); $streamA->close(); $streamB->close(); $this->assertEquals($testString, $buffer); }
public function dispose() { if (!$this->hasObservers()) { parent::dispose(); $this->stream->end(); } }
public function job($parameters) { $pretty = $this->getQueryParameter("pretty", false); if ($pretty) { $pretty = true; } $name = $parameters['name']; $method = strtolower($this->request->getMethod()); $job = $this->worker->job->getJob($name); if (!$job) { $this->response->writeHead(404, array('Content-Type' => 'text/plain')); $this->response->end("Not found\n"); $this->server->outputAccessLog($this->request, 404); return; } if ($method == 'get') { $buffer = null; $self = $this; $response = $this->response; $request = $this->request; $stream = new Stream(fopen($job->getInfoFilePath(), 'r'), $this->worker->eventLoop); $stream->on('data', function ($data, $stream) use(&$buffer) { $buffer .= $data; }); $stream->on('end', function ($stream) use($job, $response, $request, $self, &$buffer, $pretty) { $info = json_decode($buffer, true); $number = 0; if (isset($info["runtime_jobs"])) { $number = count($info["runtime_jobs"]); } $contents = []; $contents['number_of_running_jobs'] = $number; $response->writeHead(200, array('Content-Type' => 'application/json; charset=utf-8')); if ($pretty) { $output = json_encode($contents, JSON_PRETTY_PRINT); } else { $output = json_encode($contents); } $response->end($output); $self->server->outputAccessLog($request, 200); }); } elseif ($method == 'post') { $query = $this->request->getQuery(); $this->worker->job->executeJob($job, true, $query); $contents = ["status" => "OK"]; $this->response->writeHead(200, array('Content-Type' => 'application/json; charset=utf-8')); if ($pretty) { $output = json_encode($contents, JSON_PRETTY_PRINT); } else { $output = json_encode($contents); } $this->response->end($output); $this->server->outputAccessLog($this->request, 200); } else { $this->response->writeHead(400, array('Content-Type' => 'text/plain')); $this->response->end("Bad Request\n"); $this->server->outputAccessLog($this->request, 400); } }
public function __construct(LoopInterface $loop) { $bspcProcess = proc_open('pactl subscribe', [['pipe', 'r'], ['pipe', 'w']], $pipes); $bspcStdout = new Stream($pipes[1], $loop); $bspcStdout->on('data', [$this, 'onUpdate']); $loop->addTimer(0, function () { $this->queryData(); }); }
public function onData($data, Stream $conn) { $message = msgpack_unpack($data); printf("Request method: %s\n", $message['method']); printf("Request params: %s\n", print_r($message['params'], true)); $result = $this->handler->process($message); $conn->write($result); $conn->end(); }
public function __construct(LoopInterface $loop, Renderer $renderer, Stream $barStdin) { $this->loop = $loop; $this->renderer = $renderer; $lastUpdated = ''; $renderer->on('update', function ($string) use($barStdin, &$lastOutput) { if ($lastOutput != $string) { $lastOutput = $string; $barStdin->write($string . PHP_EOL); } }); }
public function __construct(Stream $stream, $protocol, $version, $code, $reasonPhrase, $headers) { $this->stream = $stream; $this->protocol = $protocol; $this->version = $version; $this->code = $code; $this->reasonPhrase = $reasonPhrase; $this->headers = $headers; $stream->on('data', array($this, 'handleData')); $stream->on('error', array($this, 'handleError')); $stream->on('end', array($this, 'handleEnd')); }
public function __construct(LoopInterface $loop, $host = 'localhost', $port = 6379, $database = 0, LoggerInterface $logger = null) { $this->logger = $logger ?? new NullLogger(); $url = 'tcp://' . $host . ':' . $port; $this->stream = stream_socket_client($url, $errno, $errstr, 30, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT); parent::__construct($this->stream, $loop); $this->on('close', function ($chunk) { $this->loop->stop(); echo 'Connection Closed' . PHP_EOL; }); $this->on('error', function ($chunk) { throw new Exception($chunk); }); $this->on('data', function ($chunk) { $this->logger->debug('Data from Redis', ['msg' => $chunk]); foreach ($this->parse($chunk) as $msg) { $type = $msg[0]; $this->emit($type, [$msg[1], $msg[2]]); } }); if ($database > 0) { if (!$this->select($database)) { throw new Exception('Error setting database index'); } } }
public function processQueue() { if ($this->commandQueue->count() == 0) { return; } if ($this->connStatus === $this::CONNECTION_BAD) { $this->failAllCommandsWith(new \Exception("Bad connection: " . $this->lastError)); $this->stream->end(); return; } while ($this->commandQueue->count() > 0 && $this->queryState === static::STATE_READY) { /** @var CommandInterface $c */ $c = $this->commandQueue->dequeue(); $this->debug("Sending " . get_class($c)); if ($c instanceof Query) { $this->debug("Sending simple query: " . $c->getQueryString()); } $this->stream->write($c->encodedMessage()); if ($c instanceof Terminate) { $this->stream->end(); } if ($c->shouldWaitForComplete()) { $this->queryState = $this::STATE_BUSY; if ($c instanceof Query) { $this->queryType = $this::QUERY_SIMPLE; } elseif ($c instanceof Sync) { $this->queryType = $this::QUERY_EXTENDED; } $this->currentCommand = $c; return; } } }
public function __construct($stream, LoopInterface $loop) { parent::__construct($stream, $loop); $this->buffer->on('full-drain', function () { $this->emit('full-drain', array($this)); }); }
/** * */ public function on() { $client = stream_socket_client('tcp://' . $this->address . ':' . $this->port); $buffer = $this->buffer; $stock = $this->stock; $conn = new Stream($client, $this->loop); $conn->on('data', function ($data) use($conn, $buffer, $stock) { $buffer->setCache($data); if (strspn($buffer->getCache(), 'close')) { $conn->close(); exit; } if (strpos($buffer->getCache(), PHP_EOL) !== false) { echo $data; } $stock->stockize($buffer->getCache()); }); }
public function handleRequest($request, $response, $connection) { $path = $this->getPath($request); $fullPath = $this->docroot . DIRECTORY_SEPARATOR . $path; echo "Loading static file: {$path}" . PHP_EOL; // if(isset($this->fileCache[$path])) { // echo "cache hit for: $path" . PHP_EOL; // $response->setBody($this->fileCache[$path]); // return $this->send($connection, $response); // } $fd = fopen($fullPath, "r"); /* @note LibEvent doesn't handle file reads asynchronously (non-blocking) */ stream_set_blocking($fd, 0); $stream = new Stream($fd, $this->loop); $this->buffer[$path] = ''; $stream->on('data', Partial\bind([$this, 'onData'], $path)); $stream->on('close', Partial\bind([$this, 'onClose'], $path, $response, $connection)); $stream->on('error', Partial\bind([$this, 'onError'], $path, $response, $connection)); }
public static function postInstall() { Config::makeBinDirectory(); $loop = Factory::create(); $file = Config::getBinFile(); $url = 'https://yt-dl.org/downloads/latest/youtube-dl'; $readStream = fopen($url, 'r'); $writeStream = fopen($file, 'w'); stream_set_blocking($readStream, 0); stream_set_blocking($writeStream, 0); $read = new Stream($readStream, $loop); $write = new Stream($writeStream, $loop); $read->on('end', function () use($file) { chmod($file, 0777); echo "Finished downloading {$file}\n"; }); $read->pipe($write); $loop->run(); }
/** * Handle http request * * @param HttpRequestEvent $event */ public function onRequest(HttpRequestEvent $event) { $filePath = $event->getRequest()->getPath(); foreach ($this->application->getMetadata() as $name => $metadata) { /* @var $metadata \PhpCollection\Map */ if ($metadata->containsKey('assets')) { $assumedFilePath = $metadata->get('application_path')->get() . DIRECTORY_SEPARATOR . $metadata->get('assets')->get() . DIRECTORY_SEPARATOR . $filePath; $assumedFilePath = realpath($assumedFilePath); if (file_exists($assumedFilePath) && is_file($assumedFilePath)) { $event->stopPropagation(); $fileStream = new Stream(fopen($assumedFilePath, 'r'), $this->serverLoop); $event->getResponse()->getHeaders()->set('Content-Type', MimeTypeGuesser::getMimeType($assumedFilePath)); $event->getResponse()->dispatchHeaders(); $fileStream->pipe($event->getResponse()->getReactResponse()); $fileStream->on('end', 'gc_collect_cycles'); gc_collect_cycles(); } } } }
public function __construct($file, $mode, $loop) { $fd = fopen($file, $mode); stream_set_blocking($fd, 0); parent::__construct($fd, $loop); $this->buffer = new BufferedSink(); $this->pipe($this->buffer); $this->on('error', function ($reason) { $this->buffer->handleErrorEvent($reason); }); }
/** * @covers React\Stream\Stream::handleData */ public function testClosingStreamInDataEventShouldNotTriggerError() { $stream = fopen('php://temp', 'r+'); $loop = $this->createLoopMock(); $conn = new Stream($stream, $loop); $conn->on(Event::DATA, function ($data, $stream) { $stream->close(); }); fwrite($stream, "foobar\n"); rewind($stream); $conn->handleData($stream); }
public function toggle(Stream $stream, $toggle) { // pause actual stream instance to continue operation on raw stream socket $stream->pause(); // TODO: add write() event to make sure we're not sending any excessive data $deferred = new Deferred(); // get actual stream socket from stream instance $socket = $stream->stream; $toggleCrypto = function () use($socket, $deferred, $toggle) { $this->toggleCrypto($socket, $deferred, $toggle); }; $this->loop->addWriteStream($socket, $toggleCrypto); $this->loop->addReadStream($socket, $toggleCrypto); $toggleCrypto(); return $deferred->promise()->then(function () use($stream) { $stream->resume(); return $stream; }, function ($error) use($stream) { $stream->resume(); throw $error; }); }
/** * @param LoopInterface $loop * @throws \LogicException */ public function start(LoopInterface $loop) { $this->input = new Stream(STDIN, $loop); $this->input->on('error', [$this, 'handleError']); $this->input->on('data', [$this, 'handleInput']); $this->output = new ConsoleOutput($loop); $this->output->on('error', [$this, 'handleError']); if ($this->isRunning()) { throw new \LogicException('The shell is already running.'); } $this->isRunning = true; $this->application->setAutoExit(false); $this->application->setCatchExceptions(true); $this->on('data', function ($command) { $ret = $this->application->run(new StringInput($command), $this->output); if (0 !== $ret) { $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret)); } }); $this->on('output', [$this, 'write']); $this->emit('running', [$this]); }
/** * @param Stream $stream * @return PromiseInterface */ public function handleInit(Stream $stream) { $this->stream = $stream; return new Promise(function (callable $fulfill, callable $reject) { $this->stream->once('data', function ($data) use($fulfill, $reject) { if (preg_match('/^ok\\b/i', $data)) { $this->stream->on('data', [$this, 'handleData']); $this->stream->on('error', [$this, 'handleError']); call_user_func($fulfill); } else { call_user_func($reject, trim($data)); } }); }); }
/** * Continues the given flow. * * @param ReactFlow $flow * @param Packet $packet */ private function continueFlow(ReactFlow $flow, Packet $packet) { try { $response = $flow->next($packet); } catch (\Exception $e) { $this->emitError($e); return; } if ($response !== null) { if ($this->stream->getBuffer()->listening) { $this->sendingFlows[] = $flow; } else { $this->stream->write($response); $this->writtenFlow = $flow; } } elseif ($flow->isFinished()) { $this->loop->nextTick(function () use($flow) { $this->finishFlow($flow); }); } }
public function probe(Stream $stream, $compression = false, $encryption = false) { $magic = Protocol::MAGIC; if ($compression) { $magic |= Protocol::FEATURE_COMPRESSION; } if ($encryption) { $magic |= Protocol::FEATURE_ENCRYPTION; } $binary = $this->binary; $stream->write($binary->writeUInt32($magic)); // list of supported protocol types (in order of preference) $types = array(Protocol::TYPE_DATASTREAM, Protocol::TYPE_LEGACY); // last item should get an END marker $last = array_pop($types); $types[] = $last | Protocol::TYPELIST_END; foreach ($types as $type) { $stream->write($binary->writeUInt32($type)); } $deferred = new Deferred(function ($resolve, $reject) use($stream) { $reject(new \RuntimeException('Cancelled')); }); $buffer = ''; $fn = function ($data) use(&$buffer, &$fn, $stream, $deferred, $binary) { $buffer .= $data; if (isset($buffer[4])) { $stream->removeListener('data', $fn); $deferred->reject(new \UnexpectedValueException('Expected 4 bytes response, received more data, is this a quassel core?', Prober::ERROR_PROTOCOL)); return; } if (isset($buffer[3])) { $stream->removeListener('data', $fn); $deferred->resolve($binary->readUInt32($buffer)); } }; $stream->on('data', $fn); $stream->on('close', function () use($deferred) { $deferred->reject(new \RuntimeException('Stream closed, does this (old?) server support probing?', Prober::ERROR_CLOSED)); }); return $deferred->promise(); }
public function __construct(Stream $stream, LoopInterface $loop) { $this->stream = $stream->stream; $this->decorating = $stream; $this->loop = $loop; $stream->on('error', function ($error) { $this->emit('error', [$error, $this]); }); $stream->on('end', function () { $this->emit('end', [$this]); }); $stream->on('close', function () { $this->emit('close', [$this]); }); $stream->on('drain', function () { $this->emit('drain', [$this]); }); $stream->pause(); $this->resume(); }
/** * */ public function close() { $this->stream->end(); $this->removeAllListeners(); }
/** * @covers React\Stream\Stream::handleData */ public function testDataErrorShouldEmitErrorAndClose() { $stream = fopen('php://temp', 'r+'); // add a filter which returns an error when encountering an 'a' when reading Filter\append($stream, function ($chunk) { if (strpos($chunk, 'a') !== false) { throw new \Exception('Invalid'); } return $chunk; }, STREAM_FILTER_READ); $loop = $this->createLoopMock(); $conn = new Stream($stream, $loop); $conn->on('data', $this->expectCallableNever()); $conn->on('error', $this->expectCallableOnce()); $conn->on('close', $this->expectCallableOnce()); fwrite($stream, "foobar\n"); rewind($stream); $conn->handleData($stream); }
<?php use React\Stream\Stream; use React\EventLoop\Factory; use Clue\React\Tar\Decoder; use React\Stream\BufferedSink; use Clue\Hexdump\Hexdump; use React\EventLoop\StreamSelectLoop; require __DIR__ . '/../vendor/autoload.php'; $in = isset($argv[1]) ? $argv[1] : __DIR__ . '/../tests/fixtures/alice-bob.tar'; echo 'Reading file "' . $in . '" (pass as argument to example)' . PHP_EOL; // using the default loop does *not* work for file I/O //$loop = Factory::create(); $loop = new StreamSelectLoop(); $stream = new Stream(fopen($in, 'r'), $loop); $decoder = new Decoder(); $decoder->on('entry', function ($header, $file) { static $i = 0; echo 'FILE #' . ++$i . PHP_EOL; echo 'Received entry headers:' . PHP_EOL; var_dump($header); BufferedSink::createPromise($file)->then(function ($contents) { echo 'Received entry contents (' . strlen($contents) . ' bytes)' . PHP_EOL; $d = new Hexdump(); echo $d->dump($contents) . PHP_EOL . PHP_EOL; }); }); $decoder->on('error', function ($error) { echo 'ERROR: ' . $error . PHP_EOL; }); $decoder->on('close', function () {
// $ echo hello | php random-colors.php // // notice how if the input contains any colors to begin with, they will be replaced // with random colors: // $ phpunit --color=always | php random-colors.php use React\Stream\Stream; use React\EventLoop\Factory; use Clue\React\Term\ControlCodeParser; require __DIR__ . '/../vendor/autoload.php'; $loop = Factory::create(); if (function_exists('posix_isatty') && posix_isatty(STDIN)) { // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); } // process control codes from STDIN $stdin = new Stream(STDIN, $loop); $parser = new ControlCodeParser($stdin); $stdout = new Stream(STDOUT, $loop); $stdout->pause(); // pass all c0 codes through to output $parser->on('c0', array($stdout, 'write')); // replace any color codes (SGR) with a random color $parser->on('csi', function ($code) use($stdout) { // we read any color code (SGR) on the input // assign a new random foreground and background color instead if (substr($code, -1) === 'm') { $code = "[" . mt_rand(30, 37) . ';' . mt_rand(40, 47) . "m"; } $stdout->write($code); }); // reset to default color at the end
/** * Wait a message result * * @param Stream $stdout Stdout Stream * @param MessageInterface $message Command waiting result * * @return mixed The result */ public function waitMessage(Stream $stdout, MessageInterface $message) { $buffer = []; $this->waitingMessageId = $message->id; $this->isWaitingMessage = true; // Read the stdin until we get the message replied while ($this->isWaitingMessage) { $this->tick(); usleep(1); } $stdout->resume(); $result = $this->waitingMessageResult; $this->waitingMessageResult = null; foreach ($this->parseMessagesBuffer as $key => $message) { $this->parseNormal($message); } $this->parseMessagesBuffer = []; return $result; }