Inheritance: extends Evenement\EventEmitter, implements React\Stream\ReadableStreamInterface, implements React\Stream\WritableStreamInterface
Example #1
0
 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);
     }
 }
Example #2
0
 public function write($data)
 {
     if (!$this->in->isWritable()) {
         throw new \Exception('Stream not writable');
     }
     $this->in->write($data);
 }
Example #3
0
 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);
 }
Example #5
0
 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);
     }
 }
Example #7
0
 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();
     });
 }
Example #8
0
 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();
 }
Example #9
0
 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);
         }
     });
 }
Example #10
0
 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'));
 }
Example #11
0
 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');
         }
     }
 }
Example #12
0
 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;
         }
     }
 }
Example #13
0
 public function __construct($stream, LoopInterface $loop)
 {
     parent::__construct($stream, $loop);
     $this->buffer->on('full-drain', function () {
         $this->emit('full-drain', array($this));
     });
 }
Example #14
0
 /**
  *
  */
 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();
 }
Example #17
0
 /**
  * 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();
             }
         }
     }
 }
Example #18
0
 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);
     });
 }
Example #19
0
 /**
  * @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);
 }
Example #20
0
 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;
     });
 }
Example #21
0
 /**
  * @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]);
 }
Example #22
0
 /**
  * @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);
         });
     }
 }
Example #24
0
 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();
 }
Example #25
0
 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();
 }
Example #26
0
 /**
  *
  */
 public function close()
 {
     $this->stream->end();
     $this->removeAllListeners();
 }
Example #27
0
 /**
  * @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);
 }
Example #28
0
<?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 () {
Example #29
0
// $ 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
Example #30
0
 /**
  * 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;
 }