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;
$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;
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 1.651 second using v1.01-cache-2.11-cpan-df04353d9ac )