File Coverage

blib/lib/Web/Async/WebSocket/Server.pm
Criterion Covered Total %
statement 12 80 15.0
branch 0 16 0.0
condition 0 9 0.0
subroutine 4 20 20.0
pod 5 13 38.4
total 21 138 15.2


line stmt bran cond sub pod time code
1             package Web::Async::WebSocket::Server;
2 1     1   256815 use Full::Class qw(:v1), extends => 'IO::Async::Notifier';
  1         147413  
  1         6  
3              
4             our $VERSION = '0.006'; ## VERSION
5             ## AUTHORITY
6              
7             =head1 NAME
8              
9             Web::Async::WebSocket::Server - L-based web+HTTP handling
10              
11             =head1 DESCRIPTION
12              
13             Provides basic websocket server implementation.
14              
15             =cut
16              
17 1     1   12090 use Ryu::Async;
  1         267774  
  1         221  
18 1     1   15 use IO::Async::Listener;
  1         2  
  1         77  
19              
20 1     1   936 use Web::Async::WebSocket::Server::Connection;
  1         5  
  1         4331  
21              
22             field $srv;
23             field $ryu : reader : param = undef;
24              
25 0     0 0   =head1 METHODS
  0            
26              
27             =head2 port
28              
29             Returns the current listening port.
30              
31             =cut
32              
33             field $port : reader : param = undef;
34              
35 0     0 1   =head2 incoming_client
  0            
36              
37             A L which emits an event every time a client connects.
38              
39             =cut
40              
41             field $incoming_client : reader : param = undef;
42              
43 0     0 1   =head2 disconnecting_client
  0            
44              
45             A L which emits an event every time a client disconnects.
46              
47             =cut
48              
49             field $disconnecting_client : reader : param = undef;
50              
51 0     0 1   =head2 closing_client
  0            
52              
53             A L which emits an event every time a client closes normally.
54              
55             =cut
56              
57             field $closing_client : reader : param = undef;
58 0     0 0   field $active_client : reader { +{ } }
  0     0 1    
  0            
59              
60 0           field $handshake : reader : param = undef;
61 0     0 0   field $on_handshake_failure : reader : param = undef;
  0            
62              
63 0     0 0   field $listening : reader = undef;
  0            
64              
65 0     0 1   method configure (%args) {
  0     0 0    
  0            
  0            
  0            
  0            
66 0 0         $port = delete $args{port} if exists $args{port};
67 0 0         $on_handshake_failure = delete $args{on_handshake_failure} if exists $args{on_handshake_failure};
68 0 0         $handshake = delete $args{handshake} if exists $args{handshake};
69 0 0         $incoming_client = delete $args{incoming_client} if exists $args{incoming_client};
70 0 0         $closing_client = delete $args{closing_client} if exists $args{closing_client};
71 0 0         $disconnecting_client = delete $args{disconnecting_client} if exists $args{disconnecting_client};
72 0           return $self->next::method(%args);
73             }
74              
75 0     0     method _add_to_loop ($loop) {
  0            
  0            
  0            
76 0 0         $self->add_child(
77             $ryu = Ryu::Async->new
78             ) unless $ryu;
79 0   0       $incoming_client //= $self->ryu->source;
80 0   0       $closing_client //= $self->ryu->source;
81 0   0       $disconnecting_client //= $self->ryu->source;
82 0           $self->add_child(
83             $srv = IO::Async::Listener->new(
84             on_stream => $self->curry::weak::on_stream,
85             )
86             );
87             $self->adopt_future(
88             $listening = $srv->listen(
89             service => $port,
90             socktype => 'stream',
91 0     0     )->on_ready(sub { undef $listening })
92 0           );
93             }
94              
95 0     0 0   method on_stream ($listener, $stream, @) {
  0            
  0            
  0            
  0            
96 0           $log->tracef('Connection %s for listener %s', "$stream", "$listener");
97             $stream->configure(
98 0     0     on_read => sub { 0 }
99 0           );
100 0           my $client = Web::Async::WebSocket::Server::Connection->new(
101             server => $self,
102             stream => $stream,
103             ryu => $ryu,
104             handshake => $handshake,
105             on_handshake_failure => $on_handshake_failure,
106             );
107 0           $active_client->{$client} = $client;
108 0           $log->infof('Client %s recorded', "$client");
109 0           $self->add_child($client);
110 0           $incoming_client->emit($client);
111 0           $self->adopt_future(
112             $client->handle_connection
113             );
114             }
115              
116 0     0 0   method on_client_close ($client, %args) {
  0            
  0            
  0            
  0            
117 0           $closing_client->emit({
118             client => $client,
119             %args,
120             });
121 0           return;
122             }
123              
124 0     0 0   method on_client_disconnect ($client, @) {
  0            
  0            
  0            
125 0           $disconnecting_client->emit({
126             client => $client
127             });
128 0 0         delete $active_client->{$client} or $log->errorf('Client %s was not recorded', "$client");
129 0           return;
130             }
131              
132             1;
133              
134             =head1 AUTHOR
135              
136             Tom Molesworth C<< >>
137              
138             =head1 LICENSE
139              
140             Copyright Tom Molesworth 2024. Licensed under the same terms as Perl itself.
141