=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