getHeader('Sec-WebSocket-Key2')); } /** * {@inheritdoc} */ public function getVersionNumber() { return 0; } /** * @param \Guzzle\Http\Message\RequestInterface $request * @return \Guzzle\Http\Message\Response * @throws \UnderflowException If there hasn't been enough data received */ public function handshake(RequestInterface $request) { $body = substr($request->getBody(), 0, 8); if (8 !== strlen($body)) { throw new \UnderflowException("Not enough data received to issue challenge response"); } $challenge = $this->sign((string)$request->getHeader('Sec-WebSocket-Key1'), (string)$request->getHeader('Sec-WebSocket-Key2'), $body); $headers = array( 'Upgrade' => 'WebSocket' , 'Connection' => 'Upgrade' , 'Sec-WebSocket-Origin' => (string)$request->getHeader('Origin') , 'Sec-WebSocket-Location' => 'ws://' . (string)$request->getHeader('Host') . $request->getPath() ); $response = new Response(101, $headers, $challenge); $response->setStatus(101, 'WebSocket Protocol Handshake'); return $response; } /** * {@inheritdoc} */ public function upgradeConnection(ConnectionInterface $conn, MessageInterface $coalescedCallback) { $upgraded = new Connection($conn); if (!isset($upgraded->WebSocket)) { $upgraded->WebSocket = new \StdClass; } $upgraded->WebSocket->coalescedCallback = $coalescedCallback; return $upgraded; } public function onMessage(ConnectionInterface $from, $data) { $overflow = ''; if (!isset($from->WebSocket->frame)) { $from->WebSocket->frame = $this->newFrame(); } $from->WebSocket->frame->addBuffer($data); if ($from->WebSocket->frame->isCoalesced()) { $overflow = $from->WebSocket->frame->extractOverflow(); $parsed = $from->WebSocket->frame->getPayload(); unset($from->WebSocket->frame); $from->WebSocket->coalescedCallback->onMessage($from, $parsed); unset($from->WebSocket->frame); } if (strlen($overflow) > 0) { $this->onMessage($from, $overflow); } } public function newFrame() { return new Frame; } public function generateKeyNumber($key) { if (0 === substr_count($key, ' ')) { return 0; } return preg_replace('[\D]', '', $key) / substr_count($key, ' '); } protected function sign($key1, $key2, $code) { return md5( pack('N', $this->generateKeyNumber($key1)) . pack('N', $this->generateKeyNumber($key2)) . $code , true); } }