NAME

Protocol::WebSocket::XS - very fast WebSocket protocol implementation

SYNOPSIS

use Protocol::WebSocket::XS::ClientParser;
use Protocol::WebSocket::XS::ServerParser;

my $client = Protocol::WebSocket::XS::ClientParser->new;
my $req_str = $client->connect_request({
    uri           => "ws://example.com/",
    ws_key        => "dGhlIHNhbXBsZSBub25jZQ==",
    ws_protocol   => "chat",
    ws_extensions => [ [ 'permessage-deflate'] ],
    headers       => {
        'Origin'          => 'http://www.crazypanda.ru',
        'User-Agent'      => 'My-UA',
    },
});

my $server = Protocol::WebSocket::XS::ServerParser->new;
my $req    = $server->accept($req_str);

my $accept_reply_str = $req->error ? $server->accept_error : $server->accept_response;
my $reply = $client->connect($accept_reply_str);   # => isa 'Protocol::WebSocket::XS::ConnectResponse'
$client->established;                       # => success
$client->is_deflate_active;                 # => success
$server->is_deflate_active;                 # => success

# control frames
my $data_1 = $client->send_control(OPCODE_PING, "hello");
my ($frame_1) = $server->get_frames($data_1);

$frame_1->payload;                          # => 'hello'
$frame_1->payload_length;                   # => 5
$frame_1->is_control;                       # => success
$frame_1->opcode;                           # => OPCODE_PING
$frame_1->final;                            # => success

# send message split by frame
my $builder = $server->start_message(opcode => OPCODE_TEXT, final => 0, deflate => 0);
my $data_2 = $builder->send("Lorem ");
my $data_3 = $builder->send("ipsum ");
my $data_4 = $builder->final(1)->send("dolor ");

my $message_data = join('', $data_2, $data_3, $data_4);
my ($message_1) = $client->get_messages($message_data);

$message_1->opcode;                         # => OPCODE_TEXT
$message_1->is_control;                     # => 0
$message_1->payload_length;                 # => 18
$message_1->payload;                        # => 'Lorem ipsum dolor '
$message_1->frame_count;                    # => 3

# convenient way just to send message
my $data_5 = $client->send_message(deflate => 1, payload => 'sit amet, ');

# pieces merged into single frame/message
my @payload_pieces = ('consectetur ', 'adipiscing ', 'elit.');
my $data_6 = $client->send_message(deflate => 0, payload => \@payload_pieces);
my $fit = $server->get_frames($data_6);    # => isa 'Protocol::WebSocket::XS::FrameIterator'
$fit->next;                                # => isa 'Protocol::WebSocket::XS::Frame'
$fit->next;                                # => undef

# pieces are send as frames; a bit faster, when you already have your data and compression
# is turned off
my $data_7 = $client->send_message_multiframe(deflate => 0, payload =>\@payload_pieces);
my $mit = $server->get_messages($data_7);  # => isa 'Protocol::WebSocket::XS::MessageIterator'
my $message_2 = $mit->next;                # => isa 'Protocol::WebSocket::XS::Message'
$message_2->frame_count;                   # => 3

# server/client configuration
my $client2 = Protocol::WebSocket::XS::ClientParser->new;
$client2->configure({
    max_frame_size     => 1024 * 10,
    max_message_size   => 1024 * 100,
    max_handshake_size => 1024 * 5,
    deflate            => {             # always on by default
        compression_threshold => 0,     # compress all TEXT-frames
    },
});

# completely disable compression; effective before connection establishment
$client2->no_deflate;

DESCRIPTION

Protocol::WebSocket::XS is a port of panda::protocol::websocket, extremely fast server/client zero-copy incremental WebSocket parser and serialization library (rfc6455) with Perl and C++ interface.

The library supports compression (a.k.a. per-message deflate extension, see rfc7692) via zlib C library, which is enabled by default for all text messages exceeding TCP max segment size (1410 bytes).

The module has dual Perl/C++ interface (see XS::Manifesto) so further XS-bindings can be written on the top of Protocol::WebSocket::XS (see UniEvent::WebSocket).

The <Protocol::WebSocket::XS> is not drop-in replacement of <Protocol::WebSocket>, as it uses sligthly different API.

PERFORMANCE

Compared to Protocol::WebSocket. Tests were performed on Xeon v3-2687W 2.9Ghz, Debian 10.

Parsing websocket packet with 200 bytes payload.

                             Rate   Protocol::WebSocket  Protocol::WebSocket::XS
Protocol::WebSocket       68593/s                     --                    -97%
Protocol::WebSocket::XS 2360644/s                  3342%                      --

CONSTANTS

Opcodes

OPCODE_CONTINUE
OPCODE_TEXT
OPCODE_BINARY
OPCODE_CLOSE
OPCODE_PING
OPCODE_PONG

Close codes

CLOSE_DONE
CLOSE_AWAY
CLOSE_PROTOCOL_ERROR
CLOSE_INVALID_DATA
CLOSE_UNKNOWN
CLOSE_ABNORMALLY
CLOSE_INVALID_TEXT
CLOSE_BAD_REQUEST
CLOSE_MAX_SIZE
CLOSE_EXTENSION_NEEDED
CLOSE_INTERNAL_ERROR
CLOSE_TLS

REFERENCE

Protocol::WebSocket::XS::ClientParser

Protocol::WebSocket::XS::ServerParser

Protocol::WebSocket::XS::Parser

Protocol::WebSocket::XS::ConnectRequest

Protocol::WebSocket::XS::ConnectResponse

Protocol::WebSocket::XS::Message

Protocol::WebSocket::XS::MessageIterator

Protocol::WebSocket::XS::Frame

Protocol::WebSocket::XS::FrameIterator

Protocol::WebSocket::XS::FrameSender

Protocol::WebSocket::XS::Error

SEE ALSO

rfc6455

rfc7692

Protocol::HTTP

Protocol::WebSocket

AUTHOR

Pronin Oleg <syber@cpan.org>, Crazy Panda LTD

Ivan Baidakou <dmol@cpan.org>, Crazy Panda LTD

LICENSE

You may distribute this code under the same terms as Perl itself.