Skip to content

Instantly share code, notes, and snippets.

@asergeyev
Created January 9, 2012 16:58
Show Gist options
  • Save asergeyev/1583872 to your computer and use it in GitHub Desktop.
Save asergeyev/1583872 to your computer and use it in GitHub Desktop.
Anyevent example for websockets to support old websocket proto from some agents (Safari, Chrome on Google TV)
<!DOCTYPE html>
<!-- mostly borrowed from Mojo -->
<html>
<head>
<title>WebSocket</title>
</head>
<body>
Testing WebSockets, please make sure you have JavaScript enabled.
</body>
</html>
<script>
var uri = "ws://"+location.host+":3000/";
var ws;
if ("MozWebSocket" in window) {
ws = new MozWebSocket(uri);
} else if ("WebSocket" in window) {
ws = new WebSocket(uri);
}
if(typeof(ws) !== 'undefined') {
function wsmessage(event) {
data = event.data;
ws.close();
alert(data);
}
function wsopen(event) {
ws.send("WebSocket support works!");
}
ws.onmessage = wsmessage;
ws.onopen = wsopen;
}
else {
alert("Sorry, your browser does not support WebSockets.");
}
</script>
#!/usr/bin/env perl
use strict;
use warnings;
use AnyEvent::Socket;
use AnyEvent::Handle;
use Protocol::WebSocket::Handshake::Server;
use Protocol::WebSocket::Frame;
my $host = shift // undef;
die "Usage: anyevent.pl [bind_ip[:bind_port]]\n" if $host && substr($host, 0, 1) eq '-';
my $port = $host && $host =~ s/\:(\d+)$//sg ? $1 : 3000;
my %clients;
AnyEvent::Socket::tcp_server $host, $port, sub {
my ($clsock, $host, $port) = @_;
my $hs = Protocol::WebSocket::Handshake::Server->new;
my $frame = Protocol::WebSocket::Frame->new;
my $client_id = $host . '.' . $port;
$clients{$client_id} = AnyEvent::Handle->new(fh => $clsock);
AE::log info => "Client $client_id connected";
my $handle_close = sub {
my $msg = pop @_;
AE::log info => "Disconnecting $client_id ($msg)";
delete $clients{$client_id};
};
$clients{$client_id}->on_read(
sub {
my $hdl = shift;
my $chunk = $hdl->{rbuf};
$hdl->{rbuf} = undef;
if (!$hs->is_done) {
$hs->parse($chunk);
if ($hs->is_done) {
$hdl->push_write($hs->to_string);
$frame->{version} = $hs->version();
AE::log info => "Upgraded $client_id to $frame->{version}";
return;
}
}
$frame->append($chunk);
while (my $message = $frame->next) {
if ($frame->is_close) { ### we are not going to support ping/pong here
$handle_close->("ws connection close");
last;
}
my $newfrm = $frame->new($message);
$newfrm->{version} = $frame->{version}; ## this could be a feature in "Frame::new"
AE::log trace => "Echoing \"$message\" to $client_id";
$hdl->push_write($newfrm->to_bytes);
}
}
);
$clients{$client_id}->on_error($handle_close);
};
my $cv = AnyEvent->condvar;
$cv->wait;
## this env recommended for looking into AE internals
AE_LOG=log=stderr:filter=info
# or even this:
# AE_LOG=log=stderr:filter=all
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment