File Coverage

blib/lib/Kamaitachi.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Kamaitachi;
2 2     2   46629 use 5.008001;
  2         9  
  2         122  
3 2     2   1137 use Moose;
  0            
  0            
4              
5             our $VERSION = '0.05';
6              
7             use IO::Handle;
8             use IO::Socket::INET;
9             use Socket qw/IPPROTO_TCP TCP_NODELAY SOCK_STREAM/;
10             use Danga::Socket;
11             use Danga::Socket::Callback;
12             use Data::AMF;
13             use Text::Glob qw/glob_to_regex/;
14              
15             use Kamaitachi::Socket;
16             use Kamaitachi::Session;
17              
18             with 'MooseX::LogDispatch';
19              
20             has port => (
21             is => 'rw',
22             isa => 'Int',
23             default => sub { 1935 },
24             );
25              
26             has sessions => (
27             is => 'rw',
28             isa => 'ArrayRef',
29             default => sub { [] },
30             );
31              
32             has parser => (
33             is => 'rw',
34             isa => 'Object',
35             lazy => 1,
36             default => sub {
37             Data::AMF->new( version => 0 ),
38             },
39             );
40              
41             has buffer_size => (
42             is => 'rw',
43             isa => 'Int',
44             default => sub { 8192 },
45             );
46              
47             has services => (
48             is => 'rw',
49             isa => 'ArrayRef',
50             default => sub { [] },
51             );
52              
53             no Moose;
54              
55             =head1 NAME
56              
57             Kamaitachi - perl flash media server
58              
59             =head1 SYNOPSIS
60              
61             use Kamaitachi;
62            
63             my $kamaitachi = Kamaitachi->new( port => 1935 );
64            
65             $kamaitachi->register_services(
66             'servive1' => 'Your::Service::Class1',
67             'servive2' => 'Your::Service::Class2',
68             );
69             $kamaitachi->run;
70              
71             =head1 DESCRIPTION
72              
73             Kamaitachi is perl implementation of Adobe's RTMP(Real Time Messaging Protocol).
74              
75             Now kamaitachi supports Remoting and MediaStreaming via RTMP. SharedObject is not implemented yet.
76              
77             This 0.x is development *alpha* version. API Interface and design are stil fluid.
78              
79             If you want to use kamaitachi, look at example directory. it contains both server script and client swf.
80              
81             =head1 DEVELOPMENT
82              
83             GitHub: http://github.com/typester/kamaitachi
84              
85             Issues: http://karas.unknownplace.org/ditz/kamaitachi/
86              
87             IRC: #kamaitachi @ chat.freenode.net
88              
89             =head1 METHODS
90              
91             =head2 new
92              
93             Kamaitachi->new( %options );
94              
95             Create kamaitachi server object.
96              
97             Available option parameters are:
98              
99             =over 4
100              
101             =item port
102              
103             port number to listen (default 1935)
104              
105             =item buffer_size
106              
107             socket buffer size to read (default 8192)
108              
109             =back
110              
111             =cut
112              
113             sub BUILD {
114             my $self = shift;
115              
116             my $ssock = IO::Socket::INET->new(
117             LocalPort => $self->port,
118             Type => SOCK_STREAM,
119             Blocking => 0,
120             ReuseAddr => 1,
121             Listen => 10,
122             ) or die $!;
123             IO::Handle::blocking($ssock, 0);
124              
125             Danga::Socket->AddOtherFds(
126             fileno($ssock) => sub {
127             my $csock = $ssock->accept or return;
128              
129             $self->logger->debug(sprintf("Listen child making a Client for %d.", fileno($csock)));
130              
131             IO::Handle::blocking($csock, 0);
132             setsockopt($csock, IPPROTO_TCP, TCP_NODELAY, pack('l', 1)) or die;
133              
134             my $session = Kamaitachi::Session->new(
135             id => fileno($csock),
136             context => $self,
137             );
138             $self->sessions->[ $session->id ] = $session;
139              
140             Kamaitachi::Socket->new(
141             handle => $csock,
142             context => $self,
143             session => $session,
144             on_read_ready => sub {
145             my $socket = shift;
146              
147             my $bref = $socket->read( $self->buffer_size );
148             unless (defined $bref) {
149             $socket->close;
150             return;
151             }
152              
153             $session->io->push($$bref);
154             $session->handler->( $session );
155             },
156             );
157             }
158             );
159             }
160              
161             =head2 register_services
162              
163             $kamaitachi->register_services(
164             'rpc/echo' => 'Service::Echo',
165             'rpc/chat' => 'Service::Chat',
166             'stream/live' => 'Service::LiveStreaming',
167             'stream/rec' => Service::LiveStreamingRecorder->new( record_output_dir => $dir ),
168             );
169              
170             Register own service classes.
171              
172             =cut
173              
174             sub register_services {
175             my ($self, @args) = @_;
176              
177             local $Text::Glob::strict_wildcard_slash = 0;
178              
179             while (@args) {
180             my $key = shift @args;
181             my $class = shift @args;
182              
183             unless (ref($class)) {
184             eval qq{ use $class };
185             die $@ if $@;
186              
187             $class = $class->new;
188             }
189              
190             push @{ $self->services }, [ glob_to_regex($key), $class ];
191             }
192             }
193              
194             =head2 run
195              
196             $kamaitachi->run
197              
198             Start kamaitachi
199              
200             =cut
201              
202             sub run {
203             my $self = shift;
204              
205             Danga::Socket->AddTimer(
206             0,
207             sub {
208             my $poll
209             = $Danga::Socket::HaveKQueue ? 'kqueue'
210             : $Danga::Socket::HaveEpoll ? 'epoll'
211             : 'poll';
212             $self->logger->debug(
213             "started kamaitachi port $self->{port} with $poll"
214             );
215             }
216             );
217              
218             Danga::Socket->EventLoop;
219             }
220              
221             =head1 AUTHOR
222              
223             Daisuke Murase <typester@cpan.org>
224              
225             Hideo Kimura <hide@cpan.org>
226              
227             =head1 COPYRIGHT
228              
229             This program is free software; you can redistribute
230             it and/or modify it under the same terms as Perl itself.
231              
232             The full text of the license can be found in the
233             LICENSE file included with this module.
234              
235             =cut
236              
237             __PACKAGE__->meta->make_immutable;