File Coverage

blib/lib/Games/IL2Device/Link.pm
Criterion Covered Total %
statement 38 124 30.6
branch 8 50 16.0
condition 3 12 25.0
subroutine 10 21 47.6
pod 0 11 0.0
total 59 218 27.0


line stmt bran cond sub pod time code
1             package Games::IL2Device::Link;
2              
3 1     1   7256 use strict;
  1         2  
  1         37  
4 1     1   6 use warnings;
  1         3  
  1         37  
5 1     1   1093 use IO::Socket qw(:DEFAULT :crlf);
  1         32668  
  1         5  
6 1     1   1079 use Carp;
  1         2  
  1         50  
7              
8 1     1   5 use vars qw($VERSION);
  1         1  
  1         1738  
9             our $VERSION = '0.02';
10              
11             our %EXPORT_TAGS = ( 'all' => [ qw(
12             ) ] );
13              
14             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15              
16             our @EXPORT = qw(
17             );
18              
19              
20              
21             # Methods
22              
23             sub new {
24 1     1 0 243 my $devlink = shift;
25 1   33     9 my $class = ref($devlink) || $devlink;
26 1         6 my $self = {
27             ADDR => undef,
28             PORT => undef,
29             TIMEOUT => 30,
30             DEBUG => 0
31             };
32 1         4 bless ($self, $class);
33 1         6 $self->_init(@_);
34 1 50 33     5 $self->il2connect if (defined($self->addr) && defined($self->port));
35 1         4 return $self;
36             }
37              
38              
39              
40             sub _init {
41 1     1   2 my $self = shift;
42 1         6 $self->{ADDR} = shift;
43 1         4 $self->{PORT} = shift;
44 1 50       5 if ( @_ ) {
45 0         0 my %extra = @_;
46 0         0 @$self{keys %extra} = values %extra;
47             }
48             }
49              
50              
51              
52             sub addr {
53 5     5 0 49 my $self = shift;
54 5 100       14 if (@_) {
55 1         3 $self->{ADDR} = shift;
56             }
57 5         31 return $self->{ADDR};
58              
59             }
60              
61              
62              
63             sub port {
64 4     4 0 7 my $self = shift;
65 4 100       106 if (@_) {
66 1         4 $self->{PORT} = shift;
67             }
68 4         35 return $self->{PORT};
69              
70             }
71              
72              
73              
74             sub reply {
75 0     0 0 0 my $self = shift;
76 0         0 return $self->{'REPLY'};
77             }
78              
79              
80              
81             sub il2connect {
82 1     1 0 3 my $self = shift;
83            
84 1 50 33     4 if ( defined($self->addr) && defined($self->port) ) {
85            
86 1 50       4 $self->{SOCK} = IO::Socket::INET->new(PeerAddr => $self->addr,
87             PeerPort => $self->port,
88             Type => SOCK_DGRAM,
89             Proto => 'udp') or
90             warn "il2connect() socket creation failed: $!";
91 1         451 return 1;
92             } else {
93 0           carp "il2connect(): Nowhere to connect!";
94 0           return 0;
95             }
96             }
97              
98              
99             sub il2disconnect {
100 0     0 0   my $self = shift;
101 0           $self->{SOCK} = undef;
102             }
103              
104              
105             sub _send {
106 0     0     my $self = shift;
107 0           local $, = $CRLF;
108 0           my $bs = 0;
109            
110 0 0         if ( defined( $self->{SOCK} ) ) {
111 0           $bs = $self->{SOCK}->print("$self->{PACKET}$CRLF");
112 0 0         warn "_send() failed to send data: $!" if $bs <= 0;
113 0 0 0       print "_send(): sent; $self->{PACKET}\n" if $self->{DEBUG} && $bs;
114             } else {
115 0           carp "_send(): No socket defined, are you connected?";
116             }
117 0           return $bs;
118             }
119            
120            
121            
122             sub _receive {
123 0     0     my $self = shift;
124 0           local $/ = $LF;
125 0           my $recv_size = ( length(scalar "$self->{PACKET}$CRLF") * 4);
126 0           my $buffer = undef;
127 0           $self->{DATA} = undef;
128            
129 0 0         if ( defined($self->{SOCK}) ) {
130 0 0         if ( $recv_size > 0 ) {
131 0     0     $SIG{ALRM} = sub { die "timeout" };
  0            
132            
133 0           eval {
134 0           alarm($self->{TIMEOUT});
135 0           $self->{SOCK}->recv($buffer, $recv_size);
136 0           $self->{DATA} = $buffer;
137 0           alarm(0);
138             };
139 0 0         if ($@) {
140 0 0         if ($@ =~ /timeout/) {
141 0           warn "_receive(): timeout while reading $!";
142             } else {
143 0           alarm(0);
144 0           die;
145             }
146             }
147            
148             }
149             } else {
150 0           carp "_receive(): No socket defined, are you connected?";
151 0           return undef;
152             }
153 0 0         print "_receive(): got: $self->{DATA}\n" if $self->{DEBUG};
154              
155 0           return $self->{DATA};
156             }
157              
158              
159             sub creategetpacket {
160 0     0 0   my $self = shift;
161 0           $self->{PACKET} = "R";
162 0           foreach ( @_ ) {
163 0           $self->{PACKET} .= "/$_";
164             }
165 0           $self->{PACKET} .= "/";
166 0 0         print "creategetpacket(): created; $self->{PACKET}\n" if $self->{DEBUG};
167 0           return $self->{PACKET};
168             }
169              
170              
171              
172             sub createsetpacket {
173 0     0 0   my $self = shift;
174 0           my ($key, $value) = @_;
175 0 0         if ( defined ($value) ) {
176 0           $self->{PACKET} = "R/" . $key . "\\" . $value;
177             } else {
178 0           $self->{PACKET} = "R/" . $key . "\\";
179             }
180 0 0         print "createsetpacket(): created; $self->{PACKET}\n" if $self->{DEBUG};
181 0           return $self->{PACKET};
182             }
183              
184              
185              
186             sub set {
187 0     0 0   my $self = shift;
188 0           my $packet = $self->createsetpacket(@_);
189 0           my $result = $self->_send($packet);
190 0           return $result;
191             }
192              
193              
194              
195             sub get {
196 0     0 0   my $self = shift;
197 0           my $data = undef;
198 0           my $packet = $self->creategetpacket(@_);
199 0           my $result = $self->_send($packet);
200 0 0         if ( defined($result) ) {
201 0           $data = $self->_receive();
202 0 0         if ( defined( $data ) ) {
203 0           $self->parsedata();
204             } else {
205 0           return 0;
206             }
207             } else {
208 0           return 0;
209             }
210 0           return 1;
211             }
212              
213              
214              
215             sub parsedata {
216 0     0 0   my $self = shift;
217 0           my %pdata;
218 0           my $key = undef;
219 0           my $value = undef;
220 0           foreach (split /\//, $self->{DATA}) {
221 0           chomp;
222 0 0         next if /^A/;
223 0 0         if ( /^(\d+)\\/ ) {
224 0           $key = $1;
225             }
226 0 0         if ( /[\\\d]*\\(.+)$/ ) {
227 0           $value = $1
228             }
229 0 0         $pdata{$key} = $value if defined $key;
230 0 0         print "parsedata(): key; $key value; $value\n" if $self->{DEBUG};
231             }
232 0           $self->{REPLY} = \%pdata;
233             }
234              
235              
236              
237             sub DESTROY {
238 0     0     my $self = shift;
239 0 0         carp "Closing connection" if $self->{DEBUG};
240 0           $self->{SOCK} = undef;
241             }
242              
243              
244             1;
245             __END__