/** * @coroutine * * @param \Icicle\Socket\Socket $socket * @param \Icicle\Http\Message\Request $request * @param mixed[] $options * * @return \Generator * * @resolve \Icicle\Http\Message\Response */ public function send(Socket $socket, Request $request, array $options = []) : \Generator { $timeout = isset($options['timeout']) ? (double) $options['timeout'] : self::DEFAULT_TIMEOUT; $allowPersistent = isset($options['allow_persistent']) ? (bool) $options['allow_persistent'] : true; $request = (yield from $this->driver->buildRequest($request, $timeout, $allowPersistent)); yield from $this->driver->writeRequest($socket, $request, $timeout); return yield from $this->driver->readResponse($socket, $timeout); }
/** * @param \Icicle\Socket\Socket $socket * @param int $cryptoMethod * @param float|int $timeout * @param bool $allowPersistent * * @return \Generator * * @resolve null */ private function process(Socket $socket, int $cryptoMethod, float $timeout, bool $allowPersistent) : \Generator { $count = 0; assert(yield from $this->log->log(Log::DEBUG, 'Accepted client from %s:%d on %s:%d', $socket->getRemoteAddress(), $socket->getRemotePort(), $socket->getLocalAddress(), $socket->getLocalPort())); try { if (0 !== $cryptoMethod) { yield from $socket->enableCrypto($cryptoMethod, $timeout); } do { $request = null; try { /** @var \Icicle\Http\Message\Request $request */ $request = (yield from $this->driver->readRequest($socket, $timeout)); ++$count; /** @var \Icicle\Http\Message\Response $response */ $response = (yield from $this->createResponse($request, $socket)); assert(yield from $this->log->log(Log::DEBUG, 'Responded to request from %s:%d for %s with %d %s', $socket->getRemoteAddress(), $socket->getRemotePort(), $request->getUri(), $response->getStatusCode(), $response->getReasonPhrase())); } catch (TimeoutException $exception) { // Request timeout. if (0 < $count) { assert(yield from $this->log->log(Log::DEBUG, 'Keep-alive timeout from %s:%d on %s:%d', $socket->getRemoteAddress(), $socket->getRemotePort(), $socket->getLocalAddress(), $socket->getLocalPort())); return; // Keep-alive timeout expired. } $response = (yield from $this->createErrorResponse(Response::REQUEST_TIMEOUT, $socket)); } catch (MessageException $exception) { // Bad request. $response = (yield from $this->createErrorResponse($exception->getCode(), $socket)); } catch (InvalidValueException $exception) { // Invalid value in message header. $response = (yield from $this->createErrorResponse(Response::BAD_REQUEST, $socket)); } catch (ParseException $exception) { // Parse error in request. $response = (yield from $this->createErrorResponse(Response::BAD_REQUEST, $socket)); } $response = (yield from $this->driver->buildResponse($response, $request, $timeout, $allowPersistent)); try { yield from $this->driver->writeResponse($socket, $response, $request, $timeout); } finally { $response->getBody()->close(); } } while (strtolower($response->getHeader('Connection')) === 'keep-alive'); } catch (Throwable $exception) { yield from $this->log->log(Log::NOTICE, "Error when handling request from %s:%d: %s", $socket->getRemoteAddress(), $socket->getRemotePort(), $exception->getMessage()); } finally { $socket->close(); } assert(yield from $this->log->log(Log::DEBUG, 'Disconnected client from %s:%d on %s:%d', $socket->getRemoteAddress(), $socket->getRemotePort(), $socket->getLocalAddress(), $socket->getLocalPort())); }