File Coverage

blib/lib/Net/Shared/Local.pm
Criterion Covered Total %
statement 64 144 44.4
branch 10 42 23.8
condition 1 6 16.6
subroutine 12 20 60.0
pod 0 13 0.0
total 87 225 38.6


line stmt bran cond sub pod time code
1 1     1   7 use strict;
  1         2  
  1         48  
2 1     1   5 use warnings;
  1         2  
  1         471  
3 1     1   88 use vars qw($VERSION);
  1         3  
  1         123  
4             $VERSION = "0.17";
5            
6             package Net::Shared::Local;
7 1     1   1687 use IO::Socket;
  1         42618  
  1         4  
8 1     1   5055 use Storable qw(freeze thaw);
  1         6892  
  1         116  
9 1     1   15 use Carp;
  1         2  
  1         2625  
10            
11             sub REAPER
12             {
13 0     0 0 0 my $waitedpid = wait;
14 0         0 $SIG{CHLD} = \&REAPER;
15             }
16             local $SIG{CHLD} = \&REAPER;
17            
18             sub new
19             {
20 2     2 0 394 my ($proto, %config) = @_;
21            
22 2   33     19 my $class = ref($proto) || $proto;
23 2         4 my $self = {};
24 2         11 bless ($self, $class);
25            
26 2 50       20 $self->{debug} = exists($config{debug}) ? $config{name} : 0;
27 2 50       20 $self->{response} = exists($config{response}) ? $config{response} : "\bl\b";
28 2         1442 $self->{name} = crypt($config{name}, $config{name});
29 2         14 $self->{ref} = $config{name};
30 2         14 $self->{data} = "";
31 2         11 $self->{port} = 0;
32 2         11 $self->{lock} = 0;
33            
34 2 100       3 $self->{accept} = defined(@{$config{accept}}) ? [@{$config{accept}}] : [qw(127.0.0.1)];
  2         12  
  1         6  
35 2         4 my $sock;
36 2 50       9 if (!exists($config{port}))
37             {
38 2         81 $sock = IO::Socket::INET->new
39             (
40             LocalAddr => 'localhost',
41             Listen => SOMAXCONN,
42             Reuse => 1,
43             Proto => 'tcp'
44             );
45            
46 2         2342 $sock->sockopt (SO_REUSEADDR, 1);
47 2         23 $sock->sockopt (SO_LINGER, 0);
48 2         28 $self->{port} = $sock->sockport;
49            
50 2         90 while()
51             {
52 2         13 my $temp = IO::Socket::INET->new(
53             Proto => 'tcp',
54             PeerAddr => 'localhost',
55             PeerPort => $self->{port}
56             );
57 2         1063 eval{$temp->connected};
  2         31  
58 2 50       269 last unless $@;
59             }
60 2         12 $sock->close;
61             }
62            
63 2 50       109 $self->{port} = $config{port} if exists($config{port});
64 2         15 $sock = IO::Socket::INET->new
65             (
66             LocalPort => $self->{port},
67             Listen => SOMAXCONN,
68             Reuse => 1,
69             Proto => 'tcp'
70             );
71 2         435 $sock->autoflush(1);
72 2 50       58 if ($config{debug})
73             {
74 0         0 print "Constructor for ", $config{name}, ":\n";
75 0         0 print "\tType of class: ", $class, "\n";
76 0         0 print "\tListening on port: ", $self->{port}, "\n";
77 0         0 print "\tAccepting from addresses:\n";
78 0         0 foreach my $address (@{$self->{accept}})
  0         0  
79             {
80 0         0 print "\t\t", $address, "\n";
81             }
82 0         0 print "\n";
83             }
84            
85 2 50       2274 croak "Can't fork: $!" unless defined ($self->{child} = fork());
86 2 50       209 if ($self->{child} == 0)
87             {
88 0         0 while (my $connection = $sock->accept)
89             {
90 0 0       0 if ($config{debug})
91             {
92 0         0 print $config{name}, " recieved a connection:\n";
93 0         0 print "\tPeerhost: ", $connection->peerhost, "\n";
94 0         0 print "\tPeerport: ", $connection->peerport, "\n";
95 0         0 print "\tLocalhost: ", $connection->sockhost, "\n";
96 0         0 print "\tLocalport: ", $connection->sockport, "\n\n";
97             }
98             do
99 0         0 {
100 0         0 $self->{incoming} = <$connection>;
101            
102 0 0       0 if (!$self->valid_header)
103             {
104 0         0 $connection->close;
105 0         0 last;
106             }
107 0 0       0 if (!$self->valid_conn(\$connection))
108             {
109 0         0 $connection->close;
110 0         0 last;
111             }
112 0 0       0 if ($self->{lock} > 1)
113             {
114 0         0 $connection->close;
115 0         0 last;
116             }
117 0 0       0 redo if ($self->{lock} > 0);
118 0         0 $self->{lock} = 1;
119            
120 0 0       0 if ($self->{incoming} ne $self->{response})
121             {
122 0         0 $self->store_data;
123             }
124             else
125             {
126 0         0 $self->send_data(\$connection);
127             }
128            
129 0         0 $self->{lock} = 0;
130 0         0 my $ok;
131 0         0 $connection->close;
132             }
133             }
134 0 0       0 $sock->close if $sock->connected;
135 0         0 exit 0;
136             }
137             else
138             {
139 2         586 return $self
140             }
141             }
142            
143             sub valid_header
144             {
145 0     0 0 0 my $self = shift;
146 0         0 my $valid = crypt($self->{name}, $self->{ref});
147 0 0       0 return if (substr($self->{incoming}, 0, length $valid) ne $valid);
148 0         0 $self->{incoming} = substr($self->{incoming}, length $valid, length($self->{incoming}) - length($valid));
149 0         0 return 1;
150             }
151            
152             sub send_data
153             {
154 0     0 0 0 my ($self, $connection) = @_;
155 0         0 my ($address,$port);
156 0         0 eval{$address = $$connection->peerhost};
  0         0  
157 0         0 eval{$port = $$connection->peerport};
  0         0  
158 0         0 $$connection->close;
159 0         0 my $sock;
160            
161 0         0 while()
162             {
163 0 0       0 $sock = IO::Socket::INET->new(
164             Proto => 'tcp',
165             PeerAddr => $address,
166             PeerPort => $port
167             ) or next;
168 0 0       0 last if $sock->connected;
169             }
170 0         0 $sock->autoflush(1);
171            
172 0 0       0 if ($self->{debug})
173             {
174 0         0 print $self->{debug}, " is sending data...\n";
175 0         0 print "\tPeerhost: ", $sock->peerhost, "\n";
176 0         0 print "\tPeerport: ", $sock->peerport, "\n";
177 0         0 print "\tLocalhost: ", $sock->sockhost, "\n";
178 0         0 print "\tLocalport: ", $sock->sockport, "\n\n";
179             }
180            
181 0         0 my $data = $self->get_data;
182 0         0 syswrite($sock, $data, length $data);
183 0         0 $sock->close;
184             }
185            
186             sub destroy_variable
187             {
188 4     4 0 6 my $self = shift;
189 4         75 kill (9, $self->{child});
190 4         76 undef $self;
191             }
192            
193             sub valid_conn
194             {
195 0     0 0 0 my ($self, $connection) = @_;
196 0         0 my $check = 0;
197 0         0 foreach my $accept (@{$self->{accept}})
  0         0  
198             {
199 0 0 0     0 $check = 1 if ($accept eq $$connection->peeraddr || $accept eq $$connection->peerhost);
200             }
201 0         0 return $check;
202             }
203            
204             sub cleanup
205             {
206 0     0 0 0 my ($self, $error_value) = @_;
207 0         0 $self->destroy_variable;
208 0         0 return $error_value;
209             }
210            
211             sub lock
212             {
213 0     0 0 0 my ($self, $status) = @_;
214 0         0 $$self->{lock} = $status;
215             }
216            
217             sub port
218             {
219 1     1 0 481 my $self = shift;
220 1         66 return $self->{port};
221             }
222            
223             sub build_header
224             {
225 6     6 0 8 my $self = shift;
226 6         497 return crypt(crypt($self->{ref},$self->{ref}),$self->{ref});
227             }
228            
229             sub prepare_data
230             {
231 3     3 0 6 my ($self,$data) = @_;
232 3         32 my $serialized_data = freeze($data);
233 3         251 return join('*',map{ord}split(//,$serialized_data));
  76         132  
234             }
235            
236             sub store_data
237             {
238 0     0 0 0 my $self = shift;
239 0         0 $self->{data} = $self->{incoming};
240 0         0 $self->{incoming} = '';
241             }
242            
243             sub get_data
244             {
245 0     0 0 0 my $self = shift;
246 0         0 return $self->{data};
247             }
248            
249             sub DESTROY
250             {
251 2     2   130 my $self = shift;
252 2         23 $self->destroy_variable;
253             }
254            
255             "JAPH";