NAME
Net::WebSocket::EV - Perl wrapper around Wslay websocket library
DESCRIPTION
Net::WebSocket::EV - websocket module based on Wslay http://wslay.sourceforge.net/. This module uses libev for doing IO.
SYNOPSIS
##### echo server #####
use Net::WebSocket::EV;
use HTTP::Server::EV;
use Digest::SHA1 qw(sha1_base64);
HTTP::Server::EV->new->listen(888, sub {
my $cgi = $_[0];
$cgi->header({
STATUS => '101 Switching Protocols',
Upgrade => "websocket",
Connection => "Upgrade",
"Sec-WebSocket-Accept" => scalar
sha1_base64( $cgi->{headers}{"Sec-WebSocket-Key"} . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ).'=',
});
$cgi->{self} = $cgi; # circular. Keep object
$cgi->{buffer}->flush_wait(sub {
$cgi->{websocket} = Net::WebSocket::EV::Server->new({
fh => $cgi->{buffer}->give_up_handle,
on_msg_recv => sub {
my ($rsv,$opcode,$msg, $status_code) = @_;
$cgi->{websocket}->queue_msg($msg);
},
on_close => sub {
my($code) = @_;
#remove circular
$cgi->{self} = undef;
$cgi = undef;
},
buffering => 1,
});
});
}, { threading => 0 });
EV::run;
METHODS
new( { params } )
Can be used as Net::WebSocket::EV::Server->new or Net::WebSocket::EV::Client->new
Params:
- fh
-
Filehandle of socket to use. Socket must be set in non blocking mode.
Net::WebSocket::EV doesn't do handshake, you must do it before calling new().
- buffering
-
If set to 0 - disables buffering. on_msg_recv is always called with empty $msg, use on_frame_recv_* to handle messages. Useful for handling big binary data without buffering it in memory.
Default if not defined : 1
- max_recv_size
-
Max message or frame size, see http://wslay.sourceforge.net/man/wslay_event_config_set_max_recv_msg_length.html
- on_msg_recv
-
This callback is called when library receives complete message. Close messages aren't handled by this callback. When buffering is disabled $msg is always empty
Callback arguments: my ($rsv, $opcode, $msg, $status_code) = @_;
- on_close
-
Called when connection is closed.
Callback arguments: my ($close_code) = @_;
- genmask
-
Used only by Net::WebSocket::EV::Client. Must return $len bytes scalar to mask message. If not specified, then simple rand() mask generator is used.
Callback arguments: my ($len) = @_;
- on_frame_recv_start
-
Called when frame header is received.
Callback arguments: my ($fin, $rsv,$opcode,$payload_length) = @_;
- on_frame_recv_chunk
-
Called when next data portion is received.
Callback arguments: my ($data) = @_;
- on_frame_recv_end
-
Called when message is received. No arguments
queue_msg( message, opcode )
Queue message, opcode is optional default is 1 (text message)
queue_fragmented ( callback, opcode )
Queue fragmented message, opcode is optional, default is 2 (binary message)
Callback arguments: my ($len) = @_;
Callback must return array of two elements ( "scalar $len or less(can be 0) bytes length", status )
Status can be:
WS_FRAGMENTED_DATA - Data chunk, optional status value, you can just return one scalar with data. Wslay will constantly reinvoke callback when it returns WS_FRAGMENTED_DATA. It will let other events run, but you will get 100% cpu load if there is no data to send and your callback always returns WS_FRAGMENTED_DATA with empty scalar while waiting for data. To prevent this use ->stop_write to suspend all IO when there is no more data to send and ->start_write when new portion of data is ready.
WS_FRAGMENTED_ERROR - Error. Don't call callback anymore
WS_FRAGMENTED_EOF - End of message.
wait(cb)
Callback called when send queue becomes empty. If callback isn't specified, then tryes to use Coro::rouse_cb & Coro::rouse_wait to block current coro.
queued_count()
Returns number of messages in send queue
start() and stop()
Start or stop all webosocket IO
start_read() and stop_write()
start_read() and stop_read()
shutdown_read() and shutdown_write()
Disable read or write. There is no way to enable it again, use start_* and stop_* instead
close( status_code, reason_data)
Queue close frame. Status and reason are optional.
Possible atack vector: client can hold connection after receiving close frame and make a lot of connections. So if you want to guaranteed close connection, then call $ws->close() and ->wait until close frame will be sent, then close socket by close($ws->{fh}).