AnyEvent-WebSocket-Server

 view release on metacpan or  search on metacpan

lib/AnyEvent/WebSocket/Server.pm  view on Meta::CPAN

=item C<ssl_cert_file> => FILE_PATH (optional)

A string of the filepath to the SSL/TLS certificate file in PEM format.

The file may contain both the certificate and corresponding private key. In that case, C<ssl_key_file> may be omitted.

If this option is set, L<AnyEvent::WebSocket::Server> encrypts the WebSocket streams with SSL/TLS.

=item C<max_payload_size> => INT (optional)

The maximum payload size for received frames. Currently defaults to whatever L<Protocol::WebSocket> defaults to.
Note that payload size for sent frames are not limited.

=back


=head1 OBJECT METHODS

=head2 $conn_cv = $server->establish($fh)

Establish a WebSocket connection to a client via the given connection filehandle.

t/connetion_active_close.t  view on Meta::CPAN

                note("server finish event fired.");
                $server_finish_called++;
                $cv_finish->end;
            });
            $conn->close();
        });
    };
    my $port = $cv_port->recv;

    my $hs = Protocol::WebSocket::Handshake::Client->new(url => $cconfig->connect_url($port, "/"));
    my $client_recv_frame = Protocol::WebSocket::Frame->new;
    my @client_recv_messages = ();
    my $client; $client = AnyEvent::Handle->new(
        $cconfig->client_handle_args($port),
        on_error => sub { fail("client handle error: $_[2]") },
        on_connect => sub {
            my ($handle) = @_;
            $cv_finish->begin;
            $handle->push_write($hs->to_string);
        },
        on_read => sub {
            my ($handle) = @_;
            if(!$hs->is_done) {
                $hs->parse($handle->{rbuf});
            }
            if($hs->is_done) {
                $client_recv_frame->append($handle->{rbuf});
                while(defined(my $message = $client_recv_frame->next_bytes)) {
                    my $opcode = $client_recv_frame->opcode;
                    push(@client_recv_messages, { opcode => $opcode, message => $message });
                    if($opcode == 8) {
                        $handle->push_write(Protocol::WebSocket::Frame->new(opcode => $opcode, buffer => $message));
                        note("client received 'close' frame. it sends back the 'close' and waits for the server to close the TCP.");
                    }
                }
            }
        },
        on_eof => sub {
            note("client TCP connection closed gracefully.");
            $cv_finish->end;
            undef $client; ## close the full connection. this is the expected behavior on any end-point, right?
        }
    );

    $cv_finish->recv;
    is($server_finish_called, 1, "server 'finish' callback is called once in response to active close.");
    is(scalar(@client_recv_messages), 1, "client received 1 message");
    is($client_recv_messages[0]{opcode}, 8, "... and it's 'close' frame (frame body is irrelevant).");
});

done_testing;

t/error.t  view on Meta::CPAN

        $cv_client_finish->recv;
        is($got_response, "", "server shuts down the connection without sending any data.");
    }
);

## No test for the case "client closes the connection right after
## sending the whole handshake request", because in this case the
## server thinks that the WebSocket connection is established, but
## disconnected immediately.

subtest "After handshake, client disconnects while sending a frame", sub {
    testlib::ConnConfig->for_all_ok_conn_configs(sub {
        my ($cconfig) = @_;
        
        my $server = AnyEvent::WebSocket::Server->new($cconfig->server_args);
        my @got_messages = ();
        my $cv_finish = AnyEvent->condvar;
        my $cv_port = start_server sub {
            my ($fh) = @_;
            $server->establish($fh)->cb(sub {
                my ($conn) = shift->recv;

t/error.t  view on Meta::CPAN

            on_connect => sub {
                my ($handle) = @_;
                $handle->push_write($hs->to_string);
            },
            on_read => sub {
                my ($handle) = @_;
                if(!$hs->is_done) {
                    $hs->parse($handle->{rbuf});
                    if($hs->is_done) {
                        $handle->push_write(Protocol::WebSocket::Frame->new("Hello, ")->to_bytes);
                        my $world_frame = Protocol::WebSocket::Frame->new("world!")->to_bytes;
                        $handle->push_write(substr($world_frame, 0, 4)); ## partial message
                        $handle->push_shutdown();
                    }
                    return;
                }
                fail("No server sent frame should be received.");
            },
            on_eof => sub {
                note("client disconnected gracefully");
            },
        );

        $cv_finish->recv;
        is_deeply(\@got_messages, ["Hello, "], "only the first message should be received. the partial message should be discarded.");
    });
};

t/max_payload_size.t  view on Meta::CPAN

use testlib::Util qw(start_server set_timeout);
use testlib::ConnConfig;
use AnyEvent::WebSocket::Server;
use AnyEvent::WebSocket::Client;

set_timeout;

my $BIG_MAX_SIZE =  99999;
my $BIG_DATA_SIZE = 99900;

subtest "server sends a big frame", sub {
    testlib::ConnConfig->for_all_ok_conn_configs(sub {
        my ($cconfig) = @_;
        my $finish_cv = AnyEvent->condvar;
        my $DATA = "a" x $BIG_DATA_SIZE;
        my $port_cv = start_server sub {
            my ($fh) = @_;
            AnyEvent::WebSocket::Server->new(
                $cconfig->server_args,
            )->establish($fh)->cb(sub {
                my ($conn) = shift->recv;

t/max_payload_size.t  view on Meta::CPAN

        )->connect($cconfig->connect_url($connect_port, "/websocket"))->recv;
        $client_conn->on(next_message => sub {
            my ($c, $message) = @_;
            is $message->body, $DATA;
            $c->close;
        });
        $finish_cv->recv;
    });
};

subtest "server receives a big frame", sub {
    testlib::ConnConfig->for_all_ok_conn_configs(sub {
        my ($cconfig) = @_;
        my $finish_cv = AnyEvent->condvar;
        my $receive_cv = AnyEvent->condvar;
        my $DATA = "a" x $BIG_DATA_SIZE;
        my $port_cv = start_server sub {
            my ($fh) = @_;
            AnyEvent::WebSocket::Server->new(
                $cconfig->server_args,
                max_payload_size => $BIG_MAX_SIZE

t/max_payload_size.t  view on Meta::CPAN

            $cconfig->client_args,
        )->connect($cconfig->connect_url($connect_port, "/websocket"))->recv;
        $client_conn->send($DATA);
        $client_conn->close;
        is $receive_cv->recv, $DATA;
        $finish_cv->recv;
    });
};


subtest "server connection emits parse_error event when receiving bigger frame than the default limit", sub {
    testlib::ConnConfig->for_all_ok_conn_configs(sub {
        my ($cconfig) = @_;
        my $parse_error_emitted = 0;
        my $port_cv = start_server sub {
            my ($fh) = @_;
            AnyEvent::WebSocket::Server->new(
                $cconfig->server_args,
            )->establish($fh)->cb(sub {
                my ($conn) = shift->recv;
                $conn->on(parse_error => sub {



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