=head1 NAME

PEF::Front::WebSocket - WebSocket framework for PEF::Front

=head1 SYNOPSIS

   # startup.pl
   use PEF::Front::Websocket;
   # usual startup stuff...

   # $PROJECT_DIR/app/WSTest/WebSocket/Echo.pm
   package WSTest::WebSocket::Echo;

   sub on_message {
       my ($self, $message) = @_;
       $self->send($message);
   }

   1;

=head1 DESCRIPTION

This module makes WebSockets really easy. Every kind of WebSocket
is in its own module. Default routing scheme is C</ws$WebSocketClass>.
WebSocket handlers are located in C<$PROJECT_DIR/app/$MyAPP/WebSocket>.

=head2 Prerequisites

This module requires L<Coro>, L<AnyEvent> and L<PSGI> server that must
meet the following requirements.

=over

=item *

C<psgi.streaming> environment is true.

=item *

C<psgi.nonblocking> environment is true.

=item *

C<psgix.io> environment holds a valid raw IO socket object. See L<PSGI::Extensions>.

=back

L<uwsgi|https://uwsgi-docs.readthedocs.io/en/latest/PSGIquickstart.html>
version 2.0.14+ meets all of them with C<psgi-enable-psgix-io = true>.

=head1 WEBSOCKET INTERFACE METHODS

=head2 on_message($message, $type)

A subroutine that is called on new message from client.

=head2 on_drain()

A subroutine that is called when there's nothing to send to
client after some successful send.

=head2 on_open()

A subroutine that is called each time it establishes a new
WebSocket connection to a client.

=head2 on_error($message)

A subroutine that is called when some error
happens while processing a request.

=head2 on_close()

A subroutine that is called on WebSocket close event.

=head2 no_compression()

When defined and true then no compression will be used even when it
supported by browser and server.

=head1 INHERITED METHODS

Every WebSocket class is derived from C<PEF::Front::Websocket::Base>
which is derived from C<PEF::Front::Websocket::Interface>. Even when you don't
derive your class from C<PEF::Front::Websocket::Base> explicitly,
this class will be added automatically to hierarchy.

=head2 send($buffer[, $type])

Sends $buffer to client. By default $type is 'text'.

=head2 close()

Closes WebSocket.

=head2 is_defunct()

Returns true when socket is closed or there's some error on it.

=head1 CONFIGURATION

=over

=item cfg_websocket_heartbeat_interval

WebSocket connection has to be B<ping>-ed to stay alive.
This paramters specifies a positive number of seconds for B<ping> interval.
Default is 30.

=item cfg_websocket_max_payload_size

Maximum payload size for incoming messages in bytes.
Default is 262144.

=item cfg_websocket_deflate_minimum_size

Minimum message size for deflate compression. If message size is less than
this value then it will not be compressed. Default is 96.

=item cfg_websocket_deflate_window_bits

WindowBits parameter for deflate compression. Default is 12.

=item cfg_websocket_deflate_memory_level

MemLevel parameter for deflate compression. Default is 5.

=back

=head1 EXAMPLE

 #startup.pl
 use WSTest::AppFrontConfig;
 use PEF::Front::Config;
 use PEF::Front::WebSocket;
 use PEF::Front::Route;

 PEF::Front::Route::add_route(
   get '/' => '/appWs',
 );
 PEF::Front::Route->to_app();


 # $PROJECT_DIR/app/WSTest/WebSocket/Echo.pm
 package WSTest::WebSocket::Echo;

 sub on_message {
     my ($self, $message) = @_;
     $self->send($message);
 }

 1;

 # $PROJECT_DIR/templates/ws.html
 <html>
 <head>
 <script language="Javascript">
   var s = new WebSocket("ws://[% hostname %]:[% request.port %]/wsEcho");
   s.onopen = function() {
       alert("connected !!!");
       s.send("ciao");
   };
   s.onmessage = function(e) {
       var bb = document.getElementById('blackboard')
       var html = bb.innerHTML;
       bb.innerHTML = html + '<br/>' + e.data;
   };
   s.onerror = function(e) {
       alert(e);
   }
   s.onclose = function(e) {
       alert("connection closed");
   }
   function invia() {
       var value = document.getElementById('testo').value;
       s.send(value);
   }
 </script>
 </head>
 <body>
   <h1>WebSocket</h1>
   <input type="text" id="testo" />
   <input type="button" value="invia" onClick="invia();" />
   <div id="blackboard"
       style="width: 640px; height: 480px; background-color: black; color: white; border: solid 2px red; overflow: auto">
   </div>
 </body>
 </html>

 # wstest.ini
 [uwsgi]
 plugins = coroae
 chdir = /$PROJECT_DIR
 logger = file:log/demo.log
 psgi = bin/startup.pl
 master = true
 processes = 4
 coroae = 1000
 perl-no-plack = true
 psgi-enable-psgix-io = true
 uid = $PROJECT_USER
 gid = www-data
 chmod-socket = 664


=head1 AUTHOR

This module was written and is maintained by Anton Petrusevich.

=head1 Copyright and License

Copyright (c) 2016 Anton Petrusevich. Some Rights Reserved.

This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

=cut