4

I have browsed the forums here and this was the closest question I found:

How to (de)construct data frames in WebSockets hybi 08+?

The difference is that I am unable to get a successful handshake. I am assuming that framing doesn't play a roll until AFTER the handshake is complete, is this correct?

I was about to launch a proof of concept when Chrome conveniently updated to version 14 which uses the HyBi 10 websocket protocol (https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-10). Based on the information in the spec on the handshake (https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-10#section-5.2.2) I have been able to successfully create a Sec-WebSocket-Accept key (success based on their example), but on the client-side the socket.onopen function never fires.

Last time I had an issue with the WebSocket protocol handshake, it was an issue with terminating the handshake with the correct bytes (or I suppose characters is more accurate?). I am using PHP for the current implementation and that has meant trying to decode Python or C# implementations, with no success so far.

Here is my client-side Javascript running in Chrome 14 (for Windows):

var socket;
socket = new WebSocket(host);
socket.onopen = function(msg){
    // process onopen
};
socket.onmessage = function(msg){ 
    // process message
};
socket.close = function(msg){
    // process close
};

And here is my server-side PHP code for the handshake:

function dohandshake($user,$buffer){
    // getheaders and calcKey are confirmed working, can provide source if desired
    list($resource,$host,$origin,$key,$version) = $this->getheaders($buffer);
    $request = "HTTP/1.1 101 Switching Protocols\r\n" .
            "Upgrade: WebSocket\r\n" .
            "Connection: Upgrade\r\n" .
            "Sec-WebSocket-Accept: " . $this->calcKey($key) . "\r\n";
    socket_write($user->socket,$request);
    $user->handshake=true;
    return true;
}

Once the client sends the initial handshake, the Javascript socket remains in the CONNECTING state indefinitely. This means onopen is never fired and so my socket stays in limbo. Any ideas on both how to debug, or even better confirm my handshake approach would be great.

Here is an apparent (I can not say whether it works for sure or not) solution in Python (https://github.com/kanaka/websockify/blob/master/websocket.py). Look for the do_handshake method.

Thanks!

Community
  • 1
  • 1
2bsharpdev
  • 285
  • 2
  • 11
  • 1
    So sorry, found my solution. It was to add another \r\n to the end of the server-side response. Once my time limit runs out, I'll post detailed answer. – 2bsharpdev Aug 14 '11 at 09:36

4 Answers4

5

So I solved my particular issue with the handshake, and it was quite noobish. I needed two sets of "\r\n" to close out the handshake. So to fix the handshake issue I described above (the Javascript WebSocket not going to the OPEN state) I needed to make the following change to my server-side PHP (note the \r\n\r\n at the end, doh):

function dohandshake($user,$buffer){
    // getheaders and calcKey are confirmed working, can provide source if desired
    list($resource,$host,$origin,$key,$version) = $this->getheaders($buffer);
    $request = "HTTP/1.1 101 Switching Protocols\r\n" .
        "Upgrade: WebSocket\r\n" .
        "Connection: Upgrade\r\n" .
        "Sec-WebSocket-Accept: " . $this->calcKey($key) . "\r\n\r\n";
    socket_write($user->socket,$request);
    $user->handshake=true;
    return true;
}

Also for future PHP-WebSocket enthusiasts I just use regular expressions to parse the header in getheaders and this is calcKey:

function calcKey($key){
     $CRAZY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
     $sha = sha1($key.$CRAZY,true);
     return base64_encode($sha);
}

Hope this helps someone else! Now to work on the message framing...

2bsharpdev
  • 285
  • 2
  • 11
  • 1
    Thanks for the solution here. Could you post all of your code? Or at least your modified getheaders() function? I want to put this together in a github project! – benathon Oct 14 '11 at 00:38
1

Here's my solution to this problem. Please post here if sometime in the distant future this code stops working!

https://github.com/esromneb/phpwebsocket/blob/master/websocket.class.php

Check out my podcast for more hacker tips! http://portforwardpodcast.com/

benathon
  • 7,455
  • 2
  • 41
  • 70
0

xsockets.net provides a serverside solution in c# if that ok? However you do not need do write any serverside code to do what you are trying todo above. Use the generic handler and only write JavaScript.

XSockets has multiprotocol support up to hybi10 with crossbrowser functionality and fallback to silverlight and flash. Also support plugins for protocols, handlers and interceptors if you want to write your own protocols etc... See the demo at http://youtu.be/MDz1jJJeXKI?hd=1

Docs at http://xsockets.net/Documentation/Index

Best Regards Uffe

Uffe
  • 2,275
  • 1
  • 13
  • 9
  • While I appreciate the response, I can't use C#, have a hard time converting it to PHP, and it doesn't appear that the server-side of XSockets is open source anyway. – 2bsharpdev Aug 14 '11 at 07:42
  • You are right, at the moment it´s only freeware. However you can add serversidecode with plugins. But if you need full opensource it is prob. wrong for you at the moment. – Uffe Aug 14 '11 at 08:00
0

Another thing... you can test the hybi10 support on JsBin. There is a multiroom chat available there with all editable code.

No flash and silverlight fallback there though!

http://jsbin.com/ohitil

/Uffe

Uffe
  • 2,275
  • 1
  • 13
  • 9