Skip to content

Commit

Permalink
Added WebSocket
Browse files Browse the repository at this point in the history
  • Loading branch information
vti committed Mar 7, 2011
1 parent 2907831 commit 8437be6
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 25 deletions.
2 changes: 1 addition & 1 deletion lib/Plack/Middleware/SocketIO.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ sub call {
my $resource = $self->resource || 'socket.io';
$resource = quotemeta $resource;

if ($env->{PATH_INFO} =~ s{^/$resource}{}) {
if ($env->{PATH_INFO} =~ m{^/$resource/}) {
my $instance = Plack::Middleware::SocketIO::Impl->instance;

return $instance->finalize($env, $self->handler)
Expand Down
8 changes: 4 additions & 4 deletions lib/Plack/Middleware/SocketIO/Base.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ sub new {
return $self;
}

sub id {
sub resource {
my $self = shift;
my ($id) = @_;
my ($resource) = @_;

return $self->{id} unless defined $id;
return $self->{resource} unless defined $resource;

$self->{id} = $id;
$self->{resource} = $resource;

return $self;
}
Expand Down
1 change: 0 additions & 1 deletion lib/Plack/Middleware/SocketIO/Handle.pm
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ sub on_read {

$self->{handle}->on_read(
sub {
warn "HANDLE READ " . $_[0]->rbuf;
$cb->($self, $_[0]->rbuf);
}
);
Expand Down
38 changes: 26 additions & 12 deletions lib/Plack/Middleware/SocketIO/Impl.pm
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,40 @@ sub finalize {
my $self = shift;
my ($env, $cb) = @_;

my $transport;
my ($resource, $type) = $env->{PATH_INFO} =~ m{^/([^\/]+)/([^\/]+)/?};
return unless $resource && $type;

if ($env->{PATH_INFO} =~ s{^/xhr-multipart/}{}) {
$transport = Plack::Middleware::SocketIO::XHRMultipart->new;
my $transport = $self->_build_transport($type, resource => $resource);
return unless $transport;

my $req = Plack::Request->new($env);

return $transport->finalize($req, $cb);
}

sub _build_transport {
my $self = shift;
my ($type, @args) = @_;

my $class;
if ($type eq 'xhr-multipart') {
$class = 'XHRMultipart';
}
elsif ($env->{PATH_INFO} =~ s{^/xhr-polling/}{}) {
$transport = Plack::Middleware::SocketIO::XHRPolling->new;
elsif ($type eq 'xhr-polling') {
$class = 'XHRPolling';
}
elsif ($env->{PATH_INFO} =~ s{^/jsonp-polling/}{}) {
$transport = Plack::Middleware::SocketIO::JSONPPolling->new;
elsif ($type eq 'jsonp-polling') {
$class = 'JSONPPolling';
}
elsif ($env->{PATH_INFO} =~ s{^/flashsocket/}{}) {
$transport = Plack::Middleware::SocketIO::WebSocket->new;
elsif ($type =~ m/^(?:flash|web)socket$/) {
$class = 'WebSocket';
}

return unless $transport;
return unless $class;

my $req = Plack::Request->new($env);
$class = "Plack::Middleware::SocketIO::$class";

return $transport->finalize($req, $cb);
return $class->new(@args);
}

sub _build_connection {
Expand Down
9 changes: 6 additions & 3 deletions lib/Plack/Middleware/SocketIO/JSONPPolling.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ sub finalize {
my $self = shift;
my ($req, $cb) = @_;

my $name = $self->name;
my $resource = $self->resource;

if ($req->method eq 'GET') {
return $self->_finalize_init($cb) if $req->path =~ m{^/\d+/\d+$};
return $self->_finalize_init($cb) if $req->path =~ m{^/$resource/$name//\d+/\d+$};

return $self->_finalize_stream($1) if $req->path =~ m{^(\d+)/\d+/\d+$};
return $self->_finalize_stream($1) if $req->path =~ m{^/$resource/$name/(\d+)/\d+/\d+$};
}

return unless $req->method eq 'POST' && $req->path =~ m{^(\d+)/\d+/\d+$};
return unless $req->method eq 'POST' && $req->path =~ m{^/$resource/$name/(\d+)/\d+/\d+$};

return $self->_finalize_send($req, $1);
}
Expand Down
81 changes: 81 additions & 0 deletions lib/Plack/Middleware/SocketIO/WebSocket.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package Plack::Middleware::SocketIO::WebSocket;

use strict;
use warnings;

use base 'Plack::Middleware::SocketIO::Base';

use Protocol::WebSocket::Frame;
use Protocol::WebSocket::Handshake::Server;

use Plack::Middleware::SocketIO::Handle;

sub name {'websocket'}

sub finalize {
my $self = shift;
my ($req, $cb) = @_;

my $fh = $req->env->{'psgix.io'};
return unless $fh;

my $hs = Protocol::WebSocket::Handshake::Server->new_from_psgi($req->env);
return unless $hs->parse($fh);

my $frame = Protocol::WebSocket::Frame->new;
my $handle = $self->_build_handle($fh);

return sub {
my $respond = shift;

$handle->write(
$hs->to_string => sub {
my $handle = shift;

my $conn = $self->add_connection(on_connect => $cb);

$handle->on_read(
sub {
my $handle = shift;

$frame->append($_[0]);

while (my $message = $frame->next) {
$conn->read($message);
}
}
);

$conn->on_write(
sub {
my $conn = shift;
my ($message) = @_;

$message = $self->_build_frame($message);

$handle->write($message);
}
);

$conn->send_id_message($conn->id);

$conn->connected unless $conn->is_connected;
}
);
};
}

sub _build_frame {
my $self = shift;
my ($message) = @_;

return Protocol::WebSocket::Frame->new($message)->to_string;
}

sub _build_handle {
my $self = shift;

return Plack::Middleware::SocketIO::Handle->new(@_);
}

1;
5 changes: 4 additions & 1 deletion lib/Plack/Middleware/SocketIO/XHRMultipart.pm
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ sub finalize {
my $self = shift;
my ($req, $cb) = @_;

my $name = $self->name;
my $resource = $self->resource;

return $self->_finalize_stream($req, $cb) if $req->method eq 'GET';

return unless $req->method eq 'POST' && $req->path =~ m{^(\d+)/send$};
return unless $req->method eq 'POST' && $req->path =~ m{^/$resource/$name/(\d+)/send$};

return $self->_finalize_send($req, $1);
}
Expand Down
9 changes: 6 additions & 3 deletions lib/Plack/Middleware/SocketIO/XHRPolling.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ sub finalize {
my $self = shift;
my ($req, $cb) = @_;

my $resource = $self->resource;
my $name = $self->name;

if ($req->method eq 'GET') {
return $self->_finalize_init($cb) if $req->path =~ m{^/\d+$};
return $self->_finalize_init($cb) if $req->path =~ m{^/$resource/$name//\d+$};

return $self->_finalize_stream($1) if $req->path =~ m{^(\d+)/\d+$};
return $self->_finalize_stream($1) if $req->path =~ m{^/$resource/$name/(\d+)/\d+$};
}

return unless $req->method eq 'POST' && $req->path_info =~ m{^(\d+)/send$};
return unless $req->method eq 'POST' && $req->path_info =~ m{^/$resource/$name/(\d+)/send$};

return $self->_finalize_send($req, $1);
}
Expand Down

0 comments on commit 8437be6

Please sign in to comment.