protected function readNextChunk() : \Generator { if ($this->expectContinue) { $expect = $this->expectContinue; $this->expectContinue = null; $this->continued = true; (yield $expect->write(Http::getStatusLine(Http::CONTINUE) . "\r\n")); } return (yield $this->stream->read($this->bufferSize)); }
/** * {@inheritdoc} */ public function upgradeConnection(HttpDriverContext $context, SocketStream $socket, HttpRequest $request, callable $action) : \Generator { if ($this->isPrefaceRequest($request)) { return yield from $this->upgradeConnectionDirect($context, $socket, $request, $action); } $settings = @\base64_decode($request->getHeaderLine('HTTP2-Settings')); if ($settings === false) { throw new StatusException(Http::CODE_BAD_REQUEST, 'HTTP/2 settings are not properly encoded'); } // Discard request body before switching to HTTP/2. (yield $request->getBody()->discard()); if ($this->logger) { $this->logger->info('{ip} "{method} {target} HTTP/{protocol}" {status} {size}', ['ip' => $request->getClientAddress(), 'method' => $request->getMethod(), 'target' => $request->getRequestTarget(), 'protocol' => $request->getProtocolVersion(), 'status' => Http::SWITCHING_PROTOCOLS, 'size' => '-']); } $buffer = Http::getStatusLine(Http::SWITCHING_PROTOCOLS, $request->getProtocolVersion()) . "\r\n"; $buffer .= "Connection: upgrade\r\n"; $buffer .= "Upgrade: h2c\r\n"; (yield $socket->write($buffer . "\r\n")); $conn = new Connection($socket, new HPack($this->hpackContext), $this->logger); (yield $conn->performServerHandshake(new Frame(Frame::SETTINGS, $settings))); if ($this->logger) { $this->logger->info('HTTP/{protocol} connection from {peer} upgraded to HTTP/2', ['protocol' => $request->getProtocolVersion(), 'peer' => $socket->getRemoteAddress()]); } $remotePeer = $socket->getRemoteAddress(); try { while (null !== ($received = (yield $conn->nextRequest($context)))) { new Coroutine($this->processRequest($conn, $action, ...$received), true); } } finally { try { $conn->shutdown(); } finally { if ($this->logger) { $this->logger->debug('Closed HTTP/2 connection to {peer}', ['peer' => $remotePeer]); } } } }