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   610764 use strict;
  29         108  
  29         920  
4 24     24   136 use warnings;
  24         58  
  24         703  
5 24     24   487 use 5.010;
  24         87  
6 24     24   1253 use Moo;
  24         24888  
  24         157  
7 24     24   26093 use AnyEvent::Handle;
  24         393864  
  24         1087  
8 24     24   12395 use AnyEvent::Socket qw( tcp_server );
  24         318751  
  24         2156  
9 24     24   11727 use AnyEvent::FTP::Server::Connection;
  24         157  
  24         1125  
10 24     24   198 use Socket qw( unpack_sockaddr_in inet_ntoa );
  24         97  
  24         27784  
11              
12             # ABSTRACT: Simple asynchronous ftp server
13             our $VERSION = '0.18'; # 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 3984 eval 'use ' . shift->default_context;
  23     23   4030  
  23         71  
  23         522  
59 28 50       323 die $@ if $@;
60             }
61              
62              
63             sub start
64             {
65 28     28 1 98 my($self) = @_;
66 28 50       317 $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   93 my($self) = @_;
130              
131             my $prepare = sub {
132 28     28   8572 my($fh, $host, $port) = @_;
133 28         304 $self->bindport($port);
134 28         194 $self->emit(bind => $port);
135 28         144 };
136              
137             my $connect = sub {
138 69     69   12348 my($fh, $host, $port) = @_;
139              
140             my $con = AnyEvent::FTP::Server::Connection->new(
141             context => $self->{default_context}->new,
142 69         2070 ip => do {
143 69         1378 my($port, $addr) = unpack_sockaddr_in getsockname $fh;
144 69         2044 inet_ntoa $addr;
145             },
146             );
147              
148 69         32082 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         5383 $con->close;
160 39         245 $handle->destroy;
161 39         1455 undef $handle;
162 39         761 undef $con;
163             },
164 69         961 );
165              
166 69         6910 $self->emit(connect => $con);
167              
168             $con->on_response(sub {
169 813         1719 my($raw) = @_;
170 813         2799 $handle->push_write($raw);
171 69         837 });
172              
173             $con->on_close(sub {
174 80         416 $handle->push_shutdown;
175 69         450 });
176              
177 69         192 $con->send_response(@{ $self->welcome });
  69         750  
178              
179             $handle->on_read(sub {
180             $handle->push_read( line => sub {
181 674         36185 my($handle, $line) = @_;
182 674         3037 $con->process_request($line);
183 674         56493 });
184 69         564 });
185              
186 28         175 };
187              
188 28   50     492 tcp_server $self->hostname, $self->port || undef, $connect, $prepare;
189              
190 28         11976 $self;
191             }
192              
193             1;
194              
195             __END__