I'am using PHP Websocket server by lemmingzshadow (web). Everything worked just fine till now.
After update to chrome 20, if I want to do handshake with server it ends with this error
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
Headers from chrome 20
GET /demo HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: gomokulive.eu:8001
Origin: http://www.gomokulive.eu
Sec-WebSocket-Key: s+AMQQu4Q10xH2AKy49byg==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Headers sent back:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: dMCVYKkF5VRrIouWFW7EYdvfD28=
Sec-WebSocket-Protocol: demo
I think problem is with "Sec-WebSocket-Extensions: x-webkit-deflate-frame" header from Chrome 20.
Any idea how to get it working again?
The server is violating the WebSocket protocol. It's likely that Chrome is just adhering to the standard more correctly in version 20 and that is revealing a bug in the server.
The problem is that the server is sending back a "Sec-WebSocket-Protocol" header in the response but this is only legal if the client sends the same header in the request. If the client does not send the Sec-WebSocket-Protocol then the server should omit the header in the response.
See the /subprotocol/ description on page 22 in Section 4.2.2 of rfc6455
A quick fix for php-websocket would be:
$response.= "Sec-WebSocket-Accept: " . $secAccept . "\r\n";
if (isset($headers['Sec-WebSocket-Protocol']))
{
$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) . "\r\n";
}
$response .= "\r\n";
An EASY way to fix is add Sec-WebSocket-Accept
information when do_handshake, code as below:
list($resource,$host,$origin,$key) = $this->getheaders($buffer);
$accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: WebSocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: {$origin}\r\n" .
"WebSocket-Location: ws://{$host}{$resource}\r\n".
"Sec-WebSocket-Accept: " . $accept . "\r\n\r\n";
$this->handshakes[$socket_index] = true;
socket_write($socket,$upgrade,strlen($upgrade));
where,
$accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$key is Sec-WebSocket-Key
got from $buffer, you can print_r($buffer) to have a look.
Hope this can solve your problem..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With