App-SocialCalc-Multiplayer

 view release on metacpan or  search on metacpan

socialcalc/third-party/lib/PocketIO/Transport/Htmlfile.pm  view on Meta::CPAN

package PocketIO::Transport::Htmlfile;

use strict;
use warnings;

use base 'PocketIO::Transport::Base';

use HTTP::Body;
use PocketIO::Response::Chunked;

sub name {'htmlfile'}

sub dispatch {
    my $self = shift;
    my ($cb) = @_;

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

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

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

    return $self->_dispatch_send($req, $1);
}

sub _dispatch_stream {
    my $self = shift;
    my ($cb) = @_;

    my $handle = $self->_build_handle($self->env->{'psgix.io'});

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

        my $close_cb = sub { $handle->close; $self->client_disconnected($conn); };
        $handle->on_eof($close_cb);
        $handle->on_error($close_cb);

        $handle->on_heartbeat(sub { $conn->send_heartbeat });

        my $id = $self->_wrap_into_script($conn->build_id_message);

        $handle->write(
            join "\x0d\x0a" => 'HTTP/1.1 200 OK',
            'Content-Type: text/html',
            'Connection: keep-alive',
            'Transfer-Encoding: chunked',
            '',
            sprintf('%x', 244 + 12),
            '<html><body>' . (' ' x 244),
            sprintf('%x', length($id)),
            $id,
            ''
        );

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

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

                $handle->write(
                    join "\x0d\x0a" => sprintf('%x', length($message)),
                    $message,
                    ''
                );
            }
        );

        $self->client_connected($conn);
    };
}

sub _dispatch_send {
    my $self = shift;
    my ($req, $id) = @_;

    my $conn = $self->find_connection($id);
    return unless $conn;

    my $raw_body = $req->content;
    my $zeros = $raw_body =~ s/\0//g;

    my $body = HTTP::Body->new($self->env->{CONTENT_TYPE},
        $self->env->{CONTENT_LENGTH} - $zeros);
    $body->add($raw_body);

    my $data = $body->param->{data};

    $conn->read($data);

    return PocketIO::Response::Chunked->finalize;
}

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

    $message =~ s/"/\\"/g;
    return qq{<script>parent.s._("$message", document);</script>};
}

1;
__END__



( run in 0.471 second using v1.01-cache-2.11-cpan-df04353d9ac )