/**
  * @param ClientInterface $client
  * @param string $input
  * @param int $length
  * @param bool $isError
  * @throws RuntimeException
  * @return RequestHandlerInterface
  */
 public function __invoke(Event $event, ClientInterface $client, $input, $length, $isError)
 {
     $this->buffer .= $input;
     $request = $this->getServiceManager()->get('Request');
     $response = $this->getServiceManager()->get('Response');
     $response->on(['ready'], function (Event $event) use($client, $request) {
         /** @var Response $response */
         $response = $event->getEventEmitter();
         $response->send($client);
     });
     while (strlen($this->buffer) > 2) {
         $offset = 0;
         $tmp = ord(substr($this->buffer, $offset++, 1));
         //            $fin = (bool) (($tmp & 0x80) >> 7);
         //            $rsv = (($tmp & 0x70) >> 4);
         //            $opcode = ($tmp & 0x0F);
         //            if ($rsv !== 0) {
         //                throw new Exception\BadRequestException('RSV bits defined while unsupported by any extension');
         //            }
         /*
          * TODO: $opcode possible values:
          *
          * %x0 denotes a continuation frame
          * %x1 denotes a text frame
          * %x2 denotes a binary frame
          * %x3-7 are reserved for further non-control frames
          * %x8 denotes a connection close
          * %x9 denotes a ping
          * %xA denotes a pong
          * %xB-F are reserved for further control frames
          */
         $tmp = ord(substr($this->buffer, $offset++, 1));
         $maskBit = (bool) ($tmp & 0x80);
         $lengthMarker = $tmp & 0x7f;
         if ($lengthMarker == 126) {
             $length = $this->_parseInt($offset, 2);
             $offset += 2;
             if ($length <= 126) {
                 throw new Exception\BadRequestException('Wrong message length.');
             }
         } else {
             if ($lengthMarker == 127) {
                 $length = $this->_parseInt($offset, 8);
                 $offset += 8;
                 if ($length <= 127) {
                     throw new Exception\BadRequestException('Wrong message length.');
                 }
             } else {
                 $length = $lengthMarker;
             }
         }
         $mask = [];
         if ($maskBit) {
             $mask = [ord(substr($this->buffer, $offset++, 1)) & 0xff, ord(substr($this->buffer, $offset++, 1)) & 0xff, ord(substr($this->buffer, $offset++, 1)) & 0xff, ord(substr($this->buffer, $offset++, 1)) & 0xff];
             //                $this->getLogger()->warning('Client data should be masked.');
         }
         if (strlen($this->buffer) < $offset + $length) {
             break;
         }
         $rawPayload = substr($this->buffer, $offset, $length);
         $this->buffer = substr($this->buffer, $offset + $length);
         if ($maskBit) {
             $payload = '';
             for ($i = 0; $i < $length; $i++) {
                 $payload .= chr(ord($rawPayload[$i]) ^ $mask[$i % 4]);
             }
         } else {
             $payload = $rawPayload;
         }
         $request->enqueue($payload);
     }
     $this->emit(new Event('data'), [$client, $request, $response]);
     return $this;
 }
 /**
  * @param Event $event
  * @param ClientInterface $client
  * @param string $buffer
  * @param int $length
  * @param bool $isError
  * @return RequestHandlerInterface
  */
 public function __invoke(Event $event, ClientInterface $client, $buffer, $length, $isError)
 {
     echo 'HTTP: Analyzing TCP request.' . PHP_EOL;
     if ($isError) {
         $response = (new Response())->setReturnCode(500, 'Internal Server Error')->setBody('Server Error')->setHeader('Connection', 'close');
         $this->emit(new Event('error'), [$response, 500, LogLevel::ERROR]);
         $response->send($client);
         return $this;
     }
     if (($request = $this->initRequest($client, $buffer, $length)) === null) {
         return $this;
     }
     if (($response = $this->initResponse($client)) === null) {
         return $this;
     }
     if ($this->setupUpgrades($client, $request, $response)) {
         return $this;
     }
     $response->on(['ready'], function (Event $event) use($client, $request) {
         /** @var ResponseInterface $response */
         $response = $event->getEventEmitter();
         $response->send($client);
     });
     // FIXME: what if the request was chunked?
     // FIXME: what if the request does not close after response?
     $this->emit(new Event('request'), [$client, $request, $response]);
     return $this;
 }