File Coverage

blib/lib/Net/Async/WebSocket/Server.pm
Criterion Covered Total %
statement 42 47 89.3
branch 4 6 66.6
condition 2 2 100.0
subroutine 10 11 90.9
pod 4 4 100.0
total 62 70 88.5


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2014 -- leonerd@leonerd.org.uk
5              
6             package Net::Async::WebSocket::Server;
7              
8 3     3   87310 use strict;
  3         8  
  3         86  
9 3     3   17 use warnings;
  3         7  
  3         97  
10 3     3   16 use base qw( IO::Async::Listener );
  3         5  
  3         2680  
11              
12 3     3   29393 use Carp;
  3         7  
  3         221  
13              
14             our $VERSION = '0.10';
15              
16 3     3   641 use Net::Async::WebSocket::Protocol;
  3         8  
  3         94  
17              
18 3     3   2612 use Protocol::WebSocket::Handshake::Server;
  3         24979  
  3         1440  
19              
20             =head1 NAME
21              
22             C - serve WebSocket clients using C
23              
24             =head1 SYNOPSIS
25              
26             use IO::Async::Loop;
27             use Net::Async::WebSocket::Server;
28              
29             my $server = Net::Async::WebSocket::Server->new(
30             on_client => sub {
31             my ( undef, $client ) = @_;
32              
33             $client->configure(
34             on_frame => sub {
35             my ( $self, $frame ) = @_;
36             $self->send_frame( $frame );
37             },
38             );
39             }
40             );
41              
42             my $loop = IO::Async::Loop->new;
43             $loop->add( $server );
44              
45             $server->listen(
46             service => 3000,
47             )->get;
48              
49             $loop->run;
50              
51             =head1 DESCRIPTION
52              
53             This subclass of L accepts WebSocket connections. When a
54             new connection arrives it will perform an initial handshake, and then pass the
55             connection on to the continuation callback or method.
56              
57             =cut
58              
59             sub new
60             {
61 2     2 1 11977 my $class = shift;
62 2         36 return $class->SUPER::new(
63             @_,
64             handle_class => "Net::Async::WebSocket::Protocol",
65             );
66             }
67              
68             sub on_accept
69             {
70 2     2 1 452 my $self = shift;
71 2         8 my ( $client ) = @_;
72              
73 2         28 my $hs = Protocol::WebSocket::Handshake::Server->new;
74              
75             $client->configure(
76             on_read => sub {
77 2     2   1380 my ( $client, $buffref, $closed ) = @_;
78              
79 2         13 $hs->parse( $$buffref ); # modifies $$buffref
80              
81 2 50       1484 if( $hs->is_done ) {
82             my $on_handshake = $self->can_event( "on_handshake" ) ||
83 2   100     39 sub { $_[3]->( 1 ) };
84              
85             $on_handshake->( $self, $client, $hs, sub {
86 2         19 my ( $ok ) = @_;
87              
88 2 50       13 unless( $ok ) {
89 0         0 $self->remove_child( $client );
90 0         0 return;
91             }
92              
93 2         9 $client->configure( on_read => undef );
94 2         155 $client->write( $hs->to_string );
95              
96 2         1198 $client->debug_printf( "HANDSHAKE done" );
97 2         21 $self->invoke_event( on_client => $client );
98 2         38 } );
99             }
100              
101 2         215 return 0;
102             },
103 2         31 );
104              
105 2         145 $self->add_child( $client );
106             }
107              
108             =head1 PARAMETERS
109              
110             The following named parameters may be passed to C or C:
111              
112             =over 8
113              
114             =item on_client => CODE
115              
116             A callback that is invoked whenever a new client connects and completes its
117             inital handshake.
118              
119             $on_client->( $self, $client )
120              
121             It will be passed a new instance of a L
122             object, wrapping the client connection.
123              
124             =item on_handshake => CODE
125              
126             A callback that is invoked when a handshake has been requested.
127              
128             $on_handshake->( $self, $client, $hs, $continuation )
129              
130             Calling C<$continuation> with a true value will complete the handshake, false
131             will drop the connection.
132              
133             This is useful for filtering on origin, for example:
134              
135             on_handshake => sub {
136             my ( $self, $client, $hs, $continuation ) = @_;
137              
138             $continuation->( $hs->req->origin eq "http://localhost" );
139             }
140              
141             =back
142              
143             =cut
144              
145             sub configure
146             {
147 2     2 1 74 my $self = shift;
148 2         6 my %params = @_;
149              
150 2         7 foreach (qw( on_client on_handshake )) {
151 4 100       22 $self->{$_} = delete $params{$_} if exists $params{$_};
152             }
153              
154 2         19 $self->SUPER::configure( %params );
155             }
156              
157             sub listen
158             {
159 0     0 1   my $self = shift;
160 0           my %params = @_;
161              
162 0           $self->SUPER::listen(
163             socktype => 'stream',
164             %params,
165             );
166             }
167              
168             =head1 AUTHOR
169              
170             Paul Evans
171              
172             =cut
173              
174             0x55AA;