File Coverage

blib/lib/CallOfDuty/LANMapper.pm
Criterion Covered Total %
statement 15 58 25.8
branch 0 8 0.0
condition n/a
subroutine 5 8 62.5
pod 2 3 66.6
total 22 77 28.5


line stmt bran cond sub pod time code
1             package CallOfDuty::LANMapper;
2              
3 1     1   26373 use 5.006;
  1         4  
  1         42  
4              
5 1     1   5 use warnings;
  1         3  
  1         28  
6 1     1   5 use strict;
  1         14  
  1         37  
7              
8 1     1   1616 use IO::Select;
  1         1763  
  1         53  
9 1     1   1989 use IO::Socket::INET;
  1         36515  
  1         8  
10              
11              
12             =head1 NAME
13              
14             CallOfDuty::LANMapper - COD Server detection and query
15              
16             =head1 VERSION
17              
18             Version 0.02
19              
20             =cut
21              
22             our $VERSION = '0.02';
23              
24              
25             =head1 SYNOPSIS
26              
27             This modules lets you detect Call Of Duty servers on your lan and query them once you know their hostname and IP.
28             Currently only Call Of Duty 4 servers are supported.
29              
30             use CallOfDuty::LANMapper;
31            
32             my $servers = CallOfDuty::LANMapper::get_servers();
33             foreach my $server ( @$servers )
34             {
35             my $info = CallOfDuty::LANMapper::get_status($server);
36             }
37              
38             =head1 FUNCTIONS
39              
40             =head2 get_servers
41              
42             my $servers = CallOfDuty::LANMapper::get_servers()
43              
44             This function broadcasts on the local network looking for Call Of Duty servers.
45              
46             An array reference containing host and port is returned e.g [ "gameserver:28960" ]
47              
48             =cut
49              
50             sub get_servers
51             {
52 0     0 1   my $servers = [];
53              
54 0           foreach my $port ( 28960 , 28961 , 28962 )
55             {
56 0           socket(my $socket, AF_INET, SOCK_DGRAM, getprotobyname('udp'));
57 0           setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 1);
58 0           my $destpaddr = sockaddr_in($port, INADDR_BROADCAST);
59 0           send($socket, 'Q', 0, $destpaddr);
60 0           my $wait = IO::Select->new($socket);
61 0           while( my ($found) = $wait->can_read(1) )
62             {
63 0           my $srcpaddr = recv($socket, my $data, 100, 0);
64 0           my ( $port , $ipaddr ) = sockaddr_in($srcpaddr);
65 0           push( @$servers , gethostbyaddr($ipaddr, AF_INET) . ":" . $port );
66             }
67 0           close $socket;
68             }
69 0           return $servers;
70             }
71              
72              
73             =head2 get_status
74              
75             my $servers = CallOfDuty::LANMapper::get_status( "localhost:28960" );
76              
77             This function contacts the call of duty server passed in and queries it for its status.
78              
79             A hash reference or undef for failure is returned. Of chief interest are the player_count field
80             which contains the number of players on the server , the player field which contains an array reference
81             which contains the current players, mapname and sv_hostname.
82              
83             =cut
84              
85             sub get_status
86             {
87 0     0 1   my ( $address ) = @_;
88 0           my $request = pack( "CCCC" , 255 , 255 , 255 , 255 ) . "getstatus xxx";
89            
90 0           my $response = generic_request( $address , $request );
91 0 0         if( !defined($response) )
92             {
93 0           return $response;
94             }
95 0           my @players = ();
96 0           while( $response->{"mod"} =~ /"([^"]+)"/g )
97             {
98 0           push( @players , $1 );
99             }
100 0           $response->{"player_count"} = scalar(@players);
101 0           $response->{"players"} = \@players;
102 0           return $response;
103             }
104              
105             #generic request sendig function
106             sub generic_request
107             {
108 0     0 0   my ( $address , $request ) = @_;
109 0           my ( $host , $port ) = split( /:/ , $address );
110 0           my $socket = IO::Socket::INET->new( LocalPort => $port , PeerPort => $port , Proto => 'udp' , PeerAddr => $host);
111 0 0         unless($socket)
112             {
113 0           warn( "could not open socket - generic - $!" );
114 0           return undef;
115             }
116              
117 0           $socket->send($request);
118              
119 0           my $wait = IO::Select->new($socket);
120 0           my $text;
121              
122 0 0         if( my ($found) = $wait->can_read(1) )
123             {
124 0           $socket->recv($text,1024);
125             }
126             else
127             {
128 0           return undef;
129             }
130              
131 0 0         if(length($text) == 0 )
132             {
133 0           return undef;
134             }
135 0           $text =~ s/.*?\\//s;
136              
137 0           my $response = {};
138 0           while( $text =~ /([^\\]+)\\([^\\]+)/g )
139             {
140 0           $response->{$1} = $2;
141             }
142            
143 0           return $response;
144             }
145              
146             =head1 AUTHOR
147              
148             Peter Sinnott, C<< >>
149              
150             =head1 BUGS
151              
152             Please report any bugs or feature requests to C, or through
153             the web interface at L. I will be notified, and then you'll
154             automatically be notified of progress on your bug as I make changes.
155              
156              
157              
158              
159             =head1 SUPPORT
160              
161             You can find documentation for this module with the perldoc command.
162              
163             perldoc CallOfDuty::LANMapper
164              
165              
166             You can also look for information at:
167              
168             =over 4
169              
170             =item * RT: CPAN's request tracker
171              
172             L
173              
174             =item * AnnoCPAN: Annotated CPAN documentation
175              
176             L
177              
178             =item * CPAN Ratings
179              
180             L
181              
182             =item * Search CPAN
183              
184             L
185              
186             =back
187              
188              
189             =head1 ACKNOWLEDGEMENTS
190              
191              
192             =head1 COPYRIGHT & LICENSE
193              
194             Copyright 2008 Peter Sinnott, all rights reserved.
195              
196             This program is free software; you can redistribute it and/or modify it
197             under the same terms as Perl itself.
198              
199              
200             =cut
201              
202             1; # End of CallOfDuty::LANMapper