there was a superfluous CR+LN with char 0x00 that was causing buffer troubles, now fixed
I am working during my free time (... recently extremely hard to have ...) over a little project that I'd like to show at the Front Trends event this October and WebSocket is the key of this project.
While 2 days ago I eventually found a way to communicate in few lines of php with a WebSocket, yesterday Chromium blog announced they "simply changed it", causing basically problems to all those projects based over the good old handshake75.
After I have found in Axod's Hack that somebody else had basically my same thoughts, I still could not find any valid example able to do the new handshake ... so here I am with the first draft-ietf-hybi-thewebsocketprotocol-00 php implementation I know, inspired somehow from the go version.
<?php
class WebSocketHandshake {
/*! Easy way to handshake a WebSocket via draft-ietf-hybi-thewebsocketprotocol-00
* @link http://www.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt
* @author Andrea Giammarchi
* @blog webreflection.blogspot.com
* @date 4th June 2010
* @example
* // via function call ...
* $handshake = WebSocketHandshake($buffer);
* // ... or via class
* $handshake = (string)new WebSocketHandshake($buffer);
*
* socket_write($socket, $handshake, strlen($handshake));
*/
private $__value__;
public function __construct($buffer) {
$resource = $host = $origin = $key1 = $key2 = $protocol = $code = $handshake = null;
preg_match('#GET (.*?) HTTP#', $buffer, $match) && $resource = $match[1];
preg_match("#Host: (.*?)\r\n#", $buffer, $match) && $host = $match[1];
preg_match("#Sec-WebSocket-Key1: (.*?)\r\n#", $buffer, $match) && $key1 = $match[1];
preg_match("#Sec-WebSocket-Key2: (.*?)\r\n#", $buffer, $match) && $key2 = $match[1];
preg_match("#Sec-WebSocket-Protocol: (.*?)\r\n#", $buffer, $match) && $protocol = $match[1];
preg_match("#Origin: (.*?)\r\n#", $buffer, $match) && $origin = $match[1];
preg_match("#\r\n(.*?)\$#", $buffer, $match) && $code = $match[1];
$this->__value__ =
"HTTP/1.1 101 WebSocket Protocol Handshake\r\n".
"Upgrade: WebSocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Origin: {$origin}\r\n".
"Sec-WebSocket-Location: ws://{$host}{$resource}\r\n".
($protocol ? "Sec-WebSocket-Protocol: {$protocol}\r\n" : "").
"\r\n".
$this->_createHandshakeThingy($key1, $key2, $code)
;
}
public function __toString() {
return $this->__value__;
}
private function _doStuffToObtainAnInt32($key) {
return preg_match_all('#[0-9]#', $key, $number) && preg_match_all('# #', $key, $space) ?
implode('', $number[0]) / count($space[0]) :
''
;
}
private function _createHandshakeThingy($key1, $key2, $code) {
return md5(
pack('N', $this->_doStuffToObtainAnInt32($key1)).
pack('N', $this->_doStuffToObtainAnInt32($key2)).
$code,
true
);
}
}
// handshake headers strings factory
function WebSocketHandshake($buffer) {
return (string)new WebSocketHandshake($buffer);
}
?>
I am pretty sure above code does not need any other comment and methods are "as much semantic as possible", since I completely agree about the Axod point and the fact it's both over engineered and absolutely badly documented via those "specs" ... weird from a company famous for its simplicity concept that maybe this time forgot some KISS approach ...
I was merrily working on my HTML5
ReplyDeleteto Asterisk PBX AMI project when
the chrome update came through
and totally changed my priorities.
Hopefully with this little hint and
a bit of luck, I'll be able to get
my little HTML5 WebSocket server
back up and running soon.
I really wish hicks and them would make better documentation BEFORE flipping the switch next time. :)
I am pretty sure above code does not need any other comment and methods are "as much semantic as possible", since I completely agree about the Axod point and the fact it's both over engineered and absolutely badly documented via those "specs"
ReplyDeleteYou haven't seen GData yet then...
Lessons learned: NOT everything is a list of things with an author and a last update date.
I wish someone would update the web-socket for nodeJS also.
ReplyDeletehttp://github.com/andregoncalves/twitter-nodejs-websocket/blob/master/vendor/ws.js
@karlnorling
ReplyDeleteThis node.js websocket module works with the new spec implementation:
http://github.com/miksago/node-websocket-server
offtopic:
ReplyDeletewe andrea
hanno inserito il type hinting sugli scalar nell'ultimo trunk di php
www.ilia.ws
GOGOGOGO
Why PHP? Rather expensive way to handle things unless your daemon/server is built from PHP itself...
ReplyDeletePHP is one of the most popular server language for web content so ... why not? Anyway, you missed the point, how to do an handshake, it does not matter with which language ;)
ReplyDeleteI use PHP quite a bit, but it requires one process for every every websocket. Thus, it won't scale for many sites (for this purpose at least, for normal web pages, ajax, etc, it is fine). That is why you never see PHP mentioned in articles about comet connections between the client and server...
ReplyDeleteSo I was definitely curious... :)
I use Flash XML sockets with PHP since ages and I have never heard PHP requires a process for each socket ... and it would be nice if you can tell me where in this page you can read such thing, thanks.
ReplyDeleteI should have said, it requires a process for every socket, unless you have built your own server in PHP itself (actually, I did write that but the browser crashed and I was lazy the second time...).
ReplyDeleteI've never seen anything other than a rudimentary http/1.0 webserver written in PHP, so I'd love to know if you built a server in PHP itself, and your experiences with doing so.
PHP was never designed to run for long periods of time, though I know that there has been effort to fix that over the years. I'm most curious about how well it scales.
select/accept methods tend to fork so they can go back and handle another client concurrently
I think it was an engineer from meebo that said they started that way (in PHP) but had to abandon it. I got some interesting pointers along the way, but always worried about investing in something I would have to switch out of later.
There is no epoll or similar for php is there?
http://htmlimg3.scribdassets.com/98pvktwsad0nk0/images/18-c72c9747be/000.png
Steven the point here is to show the handshake, PHP is just a simple way to it :)
ReplyDeletethe socket library is basically the native one, as the manual says, so socket programming a part which can be not that easy whatever language we use, I do believe PHP has not many problems there for what it offers, since socket "namespace" has been there since ages (true is that they did many nasty fixes during php 4 era)
concurrency should be handled by fixed stacks for each cycle and queued for the next iteration but I have never faced this inconvenient and I am sure if meebo guys said that there must be a valid reason (a link to that comment would be nice to better understand tho)
Regards
I really want to use PHP, and was hoping to find something on github, etc., that wasn't GPL like this:
ReplyDeletehttp://sourceforge.net/projects/comet/
And was updated over time to include, oh the subject of your post, websockets! ;)
comet and websocket are two completely different things ... where websocket wins under every aspect, imho ;)
ReplyDeleteUnfortunately, draft 76 breaks HTTP compatibility by expecting the client to send 8 bytes that are not advertised in the header due to the lack of a proper Content-Length header. This results in the protocol not being able to pass reverse-proxies nor load balancers anymore. Nice :-/
ReplyDeleteAnd if you find a hacked reverse-proxy which lets them pass, then it means it can be abused by HTTP request smugling attacks because it lets data pass before the handshake is complete.
What is a real shame is that the protocol's author says he considers a mistake to try to make Websocket and HTTP coexist on the same port :-(
With a simple modification to a script I was testing, I was able to implement your code into my test project, and successfully create a Websocket chat server via php. I couldn't figure out why Chrome 6 was failing, until I read your post. Thanks for the updates!
ReplyDeleteThanks! This has helper me a lot.
ReplyDeleteThank you for giving me the last piece(the boolean in the md5()) to make the handshaking to work.
ReplyDeleteI has been all night long searching for a solution because my old WebSocket server didn't work! I was missing the KeysAndCodeStuff xD
ReplyDeleteI love you man, thanks! I can go to sleep in peace now! ^^