File Coverage

blib/lib/Argon/Channel.pm
Criterion Covered Total %
statement 57 64 89.0
branch 1 2 50.0
condition n/a
subroutine 20 21 95.2
pod 1 5 20.0
total 79 92 85.8


line stmt bran cond sub pod time code
1             package Argon::Channel;
2             # ABSTRACT: Line protocol API for non-blocking sockets
3             $Argon::Channel::VERSION = '0.18';
4              
5 3     3   27 use strict;
  3         11  
  3         162  
6 3     3   25 use warnings;
  3         9  
  3         131  
7 3     3   20 use Carp;
  3         8  
  3         217  
8 3     3   1198 use Moose;
  3         1749141  
  3         31  
9 3     3   27272 use AnyEvent;
  3         10  
  3         99  
10 3     3   2297 use AnyEvent::Handle;
  3         26436  
  3         233  
11 3     3   1961 use Argon::Constants qw(:defaults :commands);
  3         14  
  3         816  
12 3     3   1657 use Argon::Log;
  3         12  
  3         310  
13 3     3   1384 use Argon::Marshal qw();
  3         14  
  3         88  
14 3     3   1111 use Argon::Types;
  3         17  
  3         160  
15 3     3   1274 use Argon::Util qw(K);
  3         8  
  3         1873  
16             require Argon::Message;
17              
18              
19             has fh => (
20             is => 'ro',
21             isa => 'FileHandle',
22             required => 1,
23             );
24              
25              
26             has on_msg => (
27             is => 'rw',
28             isa => 'Ar::Callback',
29             default => sub { sub{} },
30             );
31              
32              
33             has on_close => (
34             is => 'rw',
35             isa => 'Ar::Callback',
36             default => sub { sub{} },
37             );
38              
39              
40             has on_err => (
41             is => 'rw',
42             isa => 'Ar::Callback',
43             default => sub { sub{} },
44             );
45              
46             has handle => (
47             is => 'ro',
48             isa => 'Maybe[AnyEvent::Handle]',
49             lazy => 1,
50             builder => '_build_handle',
51             handles => {
52             disconnect => 'push_shutdown',
53             },
54             );
55              
56             sub _build_handle {
57 10     10   27 my $self = shift;
58 10         348 AnyEvent::Handle->new(
59             fh => $self->fh,
60             on_read => K('_read', $self),
61             on_eof => K('_eof', $self),
62             on_error => K('_error', $self),
63             );
64             }
65              
66              
67             sub BUILD {
68 10     10 0 35 my ($self, $args) = @_;
69 10         383 $self->handle;
70             }
71              
72             sub _eof {
73 2     2   8 my ($self, $handle) = @_;
74 2         84 $self->on_close->();
75 2         53 undef $self->{handle};
76             }
77              
78             sub _error {
79 0     0   0 my ($self, $handle, $fatal, $msg) = @_;
80 0         0 log_debug 'Network error: %s', $msg;
81 0         0 $self->on_err->($msg);
82 0         0 $self->disconnect;
83             }
84              
85             sub _read {
86 19     19   54 my $self = shift;
87 19         742 $self->handle->push_read(line => $EOL, K('_readline', $self));
88             }
89              
90             sub _readline {
91 19     19   85 my ($self, $handle, $line) = @_;
92 19         103 my $msg = $self->decode_msg($line);
93 19         106 $self->recv($msg);
94             }
95              
96             sub recv {
97 11     11 0 40 my ($self, $msg) = @_;
98 11         53 log_trace 'recv: %s', $msg->explain;
99 11         1622 $self->on_msg->($msg);
100             }
101              
102              
103             sub send {
104 19     19 1 2169 my ($self, $msg) = @_;
105 19         114 log_trace 'send: %s', $msg->explain;
106              
107 19         2002 my $line = $self->encode_msg($msg);
108              
109 19         21583 eval {
110 19         875 $self->handle->push_write($line);
111 19         3059 $self->handle->push_write($EOL);
112             };
113              
114 19 50       1637 if (my $error = $@) {
115 0         0 log_error 'send: remote host disconnected';
116 0         0 log_debug 'error was: %s', $error;
117 0         0 $self->_eof;
118             };
119             }
120              
121 19     19 0 98 sub encode_msg { Argon::Marshal::encode_msg($_[1]) }
122 19     19 0 5775 sub decode_msg { Argon::Marshal::decode_msg($_[1]) }
123              
124             __PACKAGE__->meta->make_immutable;
125              
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =encoding UTF-8
133              
134             =head1 NAME
135              
136             Argon::Channel - Line protocol API for non-blocking sockets
137              
138             =head1 VERSION
139              
140             version 0.18
141              
142             =head1 SYNOPSIS
143              
144             my $ch = Argon::Channel->new(
145             fh => $socket,
146             on_msg => sub {...},
147             on_close => sub {...},
148             on_err => sub {...}
149             );
150              
151             $ch->send(Argon::Message->new(...));
152              
153             =head1 DESCRIPTION
154              
155             Internal class implementing the line protocol API used for non-blocking socket
156             connections.
157              
158             =head1 ATTRIBUTES
159              
160             =head2 fh
161              
162             File handle for the connected socket. Assumed to be non-blocking.
163              
164             =head2 on_msg
165              
166             A code ref that is called when a new L<Argon::Message> arrives. The message is
167             passed as the only argument.
168              
169             =head2 on_close
170              
171             A code ref that is called when the connection is closed.
172              
173             =head2 on_err
174              
175             A code ref that is called when an error occurs during socket communication. The
176             error message is passed as the only argument.
177              
178             =head1 METHODS
179              
180             =head2 send
181              
182             Sends an L<Argon::Message> over the socket.
183              
184             =head1 AUTHOR
185              
186             Jeff Ober <sysread@fastmail.fm>
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             This software is copyright (c) 2017 by Jeff Ober.
191              
192             This is free software; you can redistribute it and/or modify it under
193             the same terms as the Perl 5 programming language system itself.
194              
195             =cut