File Coverage

blib/lib/AnyEvent/FTP/Server.pm
Criterion Covered Total %
statement 60 97 61.8
branch 2 4 50.0
condition 1 2 50.0
subroutine 14 20 70.0
pod 1 2 50.0
total 78 125 62.4


line stmt bran cond sub pod time code
1             package AnyEvent::FTP::Server;
2              
3 29     29   580819 use strict;
  29         92  
  29         979  
4 24     24   140 use warnings;
  24         51  
  24         726  
5 24     24   587 use 5.010;
  24         86  
6 24     24   1248 use Moo;
  24         23449  
  24         180  
7 24     24   27438 use AnyEvent::Handle;
  24         404048  
  24         1193  
8 24     24   14544 use AnyEvent::Socket qw( tcp_server );
  24         326639  
  24         2275  
9 24     24   13226 use AnyEvent::FTP::Server::Connection;
  24         143  
  24         1069  
10 24     24   217 use Socket qw( unpack_sockaddr_in inet_ntoa );
  24         93  
  24         28605  
11              
12             # ABSTRACT: Simple asynchronous ftp server
13             our $VERSION = '0.17'; # VERSION
14              
15              
16             $AnyEvent::FTP::Server::VERSION //= 'dev';
17              
18             with 'AnyEvent::FTP::Role::Event';
19              
20             __PACKAGE__->define_events(qw( bind connect ));
21              
22              
23             has hostname => (
24             is => 'ro',
25             );
26              
27              
28             has port => (
29             is => 'ro',
30             default => sub { 21 },
31             );
32              
33              
34             has default_context => (
35             is => 'ro',
36             default => sub { 'AnyEvent::FTP::Server::Context::FSRW' },
37             );
38              
39              
40             has welcome => (
41             is => 'ro',
42             default => sub { [ 220 => "aeftpd $AnyEvent::FTP::Server::VERSION" ] },
43             );
44              
45              
46             has bindport => (
47             is => 'rw',
48             );
49              
50              
51             has inet => (
52             is => 'ro',
53             default => sub { 0 },
54             );
55              
56             sub BUILD
57             {
58 28     28 0 2345 eval 'use ' . shift->default_context;
  23     23   4250  
  23         81  
  23         594  
59 28 50       419 die $@ if $@;
60             }
61              
62              
63             sub start
64             {
65 28     28 1 108 my($self) = @_;
66 28 50       336 $self->inet ? $self->_start_inet : $self->_start_standalone;
67             }
68              
69             sub _start_inet
70             {
71 0     0   0 my($self) = @_;
72              
73             my $con = AnyEvent::FTP::Server::Connection->new(
74             context => $self->{default_context}->new,
75 0         0 ip => do {
76 0         0 my $sockname = getsockname STDIN;
77 0         0 my ($sockport, $sockaddr) = unpack_sockaddr_in ($sockname);
78 0         0 inet_ntoa ($sockaddr);
79             },
80             );
81              
82 0         0 my $handle;
83             $handle = AnyEvent::Handle->new(
84             fh => *STDIN,
85             on_error => sub {
86 0     0   0 my($hdl, $fatal, $msg) = @_;
87 0         0 $con->close;
88 0         0 $_[0]->destroy;
89 0         0 undef $handle;
90 0         0 undef $con;
91             },
92             on_eof => sub {
93 0     0   0 $con->close;
94 0         0 $handle->destroy;
95 0         0 undef $handle;
96 0         0 undef $con;
97             },
98 0         0 );
99              
100 0         0 $self->emit(connect => $con);
101              
102 0         0 STDOUT->autoflush(1);
103 0         0 STDIN->autoflush(1);
104              
105             $con->on_response(sub {
106 0     0   0 my($raw) = @_;
107 0         0 print STDOUT $raw;
108 0         0 });
109              
110             $con->on_close(sub {
111 0     0   0 close STDOUT;
112 0         0 exit;
113 0         0 });
114              
115 0         0 $con->send_response(@{ $self->welcome });
  0         0  
116              
117             $handle->on_read(sub {
118             $handle->push_read( line => sub {
119 0         0 my($handle, $line) = @_;
120 0         0 $con->process_request($line);
121 0     0   0 });
122 0         0 });
123              
124 0         0 $self;
125             }
126              
127             sub _start_standalone
128             {
129 28     28   99 my($self) = @_;
130              
131             my $prepare = sub {
132 28     28   8785 my($fh, $host, $port) = @_;
133 28         352 $self->bindport($port);
134 28         198 $self->emit(bind => $port);
135 28         158 };
136              
137             my $connect = sub {
138 69     69   12275 my($fh, $host, $port) = @_;
139              
140             my $con = AnyEvent::FTP::Server::Connection->new(
141             context => $self->{default_context}->new,
142 69         1885 ip => do {
143 69         1466 my($port, $addr) = unpack_sockaddr_in getsockname $fh;
144 69         1974 inet_ntoa $addr;
145             },
146             );
147              
148 69         32956 my $handle;
149             $handle = AnyEvent::Handle->new(
150             fh => $fh,
151             on_error => sub {
152 0         0 my($hdl, $fatal, $msg) = @_;
153 0         0 $con->close;
154 0         0 $_[0]->destroy;
155 0         0 undef $handle;
156 0         0 undef $con;
157             },
158             on_eof => sub {
159 39         5145 $con->close;
160 39         186 $handle->destroy;
161 39         1297 undef $handle;
162 39         640 undef $con;
163             },
164 69         1004 );
165              
166 69         7417 $self->emit(connect => $con);
167              
168             $con->on_response(sub {
169 813         1653 my($raw) = @_;
170 813         3107 $handle->push_write($raw);
171 69         670 });
172              
173             $con->on_close(sub {
174 80         340 $handle->push_shutdown;
175 69         436 });
176              
177 69         146 $con->send_response(@{ $self->welcome });
  69         660  
178              
179             $handle->on_read(sub {
180             $handle->push_read( line => sub {
181 674         37224 my($handle, $line) = @_;
182 674         2765 $con->process_request($line);
183 674         56941 });
184 69         624 });
185              
186 28         201 };
187              
188 28   50     569 tcp_server $self->hostname, $self->port || undef, $connect, $prepare;
189              
190 28         11612 $self;
191             }
192              
193             1;
194              
195             __END__