| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Tak::Daemon::ListenerService; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
33676
|
use Scalar::Util qw(weaken); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
138
|
|
|
4
|
1
|
|
|
1
|
|
3116
|
use Moo; |
|
|
1
|
|
|
|
|
18726
|
|
|
|
1
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
with 'Tak::Role::Service'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
has listen_on => (is => 'ro', required => 1); |
|
9
|
|
|
|
|
|
|
has router => (is => 'ro', required => 1); |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has state => (is => 'rw', default => sub { 'down' }, init_arg => undef); |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
has _start_in_progress => (is => 'lazy', clearer => '_clear_start_in_progress'); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has listener => (is => 'rw', clearer => 'clear_listener'); |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
has connections => (is => 'ro', default => sub { {} }); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub start_start_request { |
|
20
|
0
|
|
|
0
|
|
|
my ($self, $req) = @_; |
|
21
|
0
|
0
|
|
|
|
|
$req->result('already_started') if $self->state eq 'running'; |
|
22
|
0
|
|
|
|
|
|
push(@{$self->_start_in_progress->{requests}}, $req); |
|
|
0
|
|
|
|
|
|
|
|
23
|
0
|
|
|
|
|
|
$self->_start_in_progress->{start}(); |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub _build__start_in_progress { |
|
27
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
28
|
0
|
|
|
|
|
|
weaken($self); |
|
29
|
0
|
|
|
|
|
|
my %start = (requests => (my $requests = [])); |
|
30
|
0
|
|
|
|
|
|
my $listen_on = $self->listen_on; |
|
31
|
0
|
0
|
|
|
|
|
my %addr = ( |
|
32
|
|
|
|
|
|
|
socktype => "stream", |
|
33
|
|
|
|
|
|
|
map +( |
|
34
|
|
|
|
|
|
|
ref($_) |
|
35
|
|
|
|
|
|
|
? (family => "inet", %$_) |
|
36
|
|
|
|
|
|
|
: (family => "unix", path => $_) |
|
37
|
|
|
|
|
|
|
), $listen_on |
|
38
|
|
|
|
|
|
|
); |
|
39
|
|
|
|
|
|
|
$start{start} = sub { |
|
40
|
0
|
|
|
0
|
|
|
$self->state('starting'); |
|
41
|
0
|
|
|
|
|
|
Tak->loop_upgrade; |
|
42
|
|
|
|
|
|
|
Tak->loop->listen( |
|
43
|
|
|
|
|
|
|
addr => \%addr, |
|
44
|
|
|
|
|
|
|
on_notifier => sub { |
|
45
|
0
|
|
|
|
|
|
$self->listener($_[0]); |
|
46
|
0
|
|
|
|
|
|
$_->success('started') for @$requests; |
|
47
|
0
|
|
|
|
|
|
$self->_clear_start_in_progress; |
|
48
|
0
|
|
|
|
|
|
$self->state('running'); |
|
49
|
|
|
|
|
|
|
}, |
|
50
|
|
|
|
|
|
|
on_resolve_error => sub { # no-op until we add non-unix |
|
51
|
0
|
|
|
|
|
|
$_->failure(resolve => @_) for @$requests; |
|
52
|
0
|
|
|
|
|
|
$self->_clear_start_in_progress; |
|
53
|
0
|
|
|
|
|
|
$self->state('stopped'); |
|
54
|
|
|
|
|
|
|
}, |
|
55
|
|
|
|
|
|
|
on_listen_error => sub { |
|
56
|
0
|
|
|
|
|
|
$_->failure(listen => @_) for @$requests; |
|
57
|
0
|
|
|
|
|
|
$self->_clear_start_in_progress; |
|
58
|
0
|
|
|
|
|
|
$self->state('stopped'); |
|
59
|
|
|
|
|
|
|
}, |
|
60
|
|
|
|
|
|
|
on_accept => sub { |
|
61
|
0
|
|
|
|
|
|
$self->setup_connection($_[0]); |
|
62
|
|
|
|
|
|
|
}, |
|
63
|
|
|
|
|
|
|
on_accept_error => sub { |
|
64
|
0
|
|
|
|
|
|
$self->handle_stop; |
|
65
|
|
|
|
|
|
|
}, |
|
66
|
0
|
|
|
|
|
|
); |
|
67
|
0
|
|
|
|
|
|
$start{start} = sub {}; # delete yourself |
|
|
0
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
}; |
|
69
|
0
|
|
|
|
|
|
\%start; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub handle_stop { |
|
73
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
74
|
0
|
0
|
|
|
|
|
return 'already_stopped' if $self->state eq 'down'; |
|
75
|
|
|
|
|
|
|
# there's probably something more intelligent to do here, but meh |
|
76
|
0
|
0
|
|
|
|
|
die failure => 'starting' if $self->state eq 'starting'; |
|
77
|
0
|
|
|
|
|
|
Tak->loop->remove($self->clear_listener); |
|
78
|
0
|
|
0
|
|
|
|
!ref and unlink($_) for $self->listen_on; |
|
79
|
0
|
|
|
|
|
|
$self->state('down'); |
|
80
|
0
|
|
|
|
|
|
return 'stopped'; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub DEMOLISH { |
|
84
|
0
|
|
|
0
|
|
|
my ($self, $in_global_destruction) = @_; |
|
85
|
|
|
|
|
|
|
|
|
86
|
0
|
0
|
|
|
|
|
return unless $self->state eq 'running'; |
|
87
|
|
|
|
|
|
|
|
|
88
|
0
|
|
0
|
|
|
|
!ref and unlink($_) for $self->listen_on; |
|
89
|
|
|
|
|
|
|
|
|
90
|
0
|
0
|
|
|
|
|
return if $in_global_destruction; |
|
91
|
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
Tak->loop->remove($self->listener); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub setup_connection { |
|
96
|
0
|
|
|
0
|
|
|
my ($self, $socket) = @_; |
|
97
|
0
|
|
|
|
|
|
my $conn_set = $self->connections; |
|
98
|
0
|
|
|
|
|
|
my $conn_str; |
|
99
|
|
|
|
|
|
|
my $connection = Tak::ConnectionService->new( |
|
100
|
|
|
|
|
|
|
read_fh => $socket, write_fh => $socket, |
|
101
|
|
|
|
|
|
|
listening_service => $self->router->clone_or_self, |
|
102
|
0
|
|
|
0
|
|
|
on_close => sub { delete $conn_set->{$conn_str} } |
|
103
|
0
|
|
|
|
|
|
); |
|
104
|
0
|
|
|
|
|
|
$conn_str = "$connection"; |
|
105
|
0
|
|
|
|
|
|
$connection->receiver->service->service->register_weak(remote => $connection); |
|
106
|
0
|
|
|
|
|
|
$conn_set->{$conn_str} = $connection; |
|
107
|
0
|
|
|
|
|
|
return; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
1; |