Exemplo n.º 1
0
 protected function createSocketChannel($socket, int $chunkSize, int $length = null) : Channel
 {
     $size = (int) \max(1, \ceil(65535 / $chunkSize));
     return Channel::fromGenerator($size, function (Channel $channel) use($socket, $length, $chunkSize) {
         $reader = new SocketReader($socket);
         $remaining = $length ?? \PHP_INT_MAX;
         try {
             while ($remaining && null !== ($chunk = (yield $reader->readBuffer(\min($remaining, $chunkSize))))) {
                 $remaining -= \strlen($chunk);
                 (yield $channel->send($chunk));
             }
         } finally {
             $reader->dispose();
         }
     });
 }
Exemplo n.º 2
0
 /**
  * {@inheritdoc}
  */
 public function channel(int $chunkSize = 4096, int $length = null) : Channel
 {
     return Channel::fromGenerator(16, function (Channel $channel) use($chunkSize, $length) {
         (yield $this->executor->execute(function () use($channel, $chunkSize, $length) {
             $remaining = $length ?? \PHP_INT_MAX;
             while ($remaining && null !== ($chunk = (yield $this->stream->readBuffer(\min($remaining, $chunkSize))))) {
                 $remaining -= \strlen($chunk);
                 (yield $channel->send($chunk));
             }
         }));
     });
 }
Exemplo n.º 3
0
 /**
  * {@inheritdoc}
  */
 public function channel(int $chunkSize = 4096, int $length = null) : Channel
 {
     $size = (int) \max(1, \ceil($this->readBufferSize / $chunkSize));
     return Channel::fromGenerator($size, function (Channel $channel) use($chunkSize, $length) {
         $remaining = $length ?? \PHP_INT_MAX;
         while ($remaining && null !== ($chunk = (yield $this->readBuffer(\min($remaining, $chunkSize))))) {
             $remaining -= \strlen($chunk);
             (yield $channel->send($chunk));
         }
     });
 }
Exemplo n.º 4
0
 /**
  * {@inheritdoc}
  */
 public function handleConnection(HttpDriverContext $context, SocketStream $socket, callable $action) : Awaitable
 {
     return new Coroutine(function () use($context, $socket, $action) {
         $remotePeer = $socket->getRemoteAddress();
         $upgraded = false;
         if ($this->logger) {
             $this->logger->debug('Accepted new HTTP/1 connection from {peer}', ['peer' => $remotePeer]);
         }
         try {
             $request = (yield from $this->parseNextRequest($context, $socket));
             if ($request->getProtocolVersion() !== '1.0' && $request->hasHeader('Host')) {
                 try {
                     yield from $this->upgradeConnection($context, $socket, $request, $action, $upgraded);
                     if ($upgraded) {
                         return;
                     }
                 } catch (\Throwable $e) {
                     return yield from $this->sendErrorResponse($socket, $request, $e);
                 }
             }
             $tokens = $request->getHeaderTokenValues('Connection');
             if (\in_array('upgrade', $tokens, true)) {
                 foreach ($tokens as $i => $token) {
                     if ($token === 'keep-alive') {
                         unset($tokens[$i]);
                     }
                 }
                 // Ensure connections with an upgrade token in the connection header are not pipelined / persistent.
                 $request = $request->withHeader('Connection', \implode(', ', \array_merge($tokens, ['close'])));
             }
             $pipeline = Channel::fromGenerator(10, function (Channel $channel) use($socket, $request, $context) {
                 yield from $this->parseIncomingRequests($context, $socket, $channel, $request);
             });
             try {
                 while (null !== ($next = (yield $pipeline->receive()))) {
                     if (!(yield from $this->processRequest($context, $socket, $action, $upgraded, ...$next))) {
                         break;
                     }
                 }
                 $pipeline->close();
             } catch (\Throwable $e) {
                 $pipeline->close($e);
             }
         } finally {
             try {
                 $socket->close();
             } finally {
                 if ($this->logger && !$upgraded) {
                     $this->logger->debug('Closed HTTP/1 connection to {peer}', ['peer' => $remotePeer]);
                 }
             }
         }
     });
 }