diff options
| author | Darkelarious <darkelarious@333networks.com> | 2016-11-19 20:56:04 +0100 |
|---|---|---|
| committer | Darkelarious <darkelarious@333networks.com> | 2016-11-19 20:56:04 +0100 |
| commit | c3f8d65a4fb1f5674557ee67cf7f74369df86ad1 (patch) | |
| tree | 92aab2a394bda28da0ed7c7c75e633fdf386fc71 /util/tools/r_functions.pl | |
| parent | 1de3da4b8027508a91144639455c934fd6ccb9b7 (diff) | |
| download | MasterServer-Perl-c3f8d65a4fb1f5674557ee67cf7f74369df86ad1.tar.gz MasterServer-Perl-c3f8d65a4fb1f5674557ee67cf7f74369df86ad1.zip | |
Massive improvements on efficiency, robustness, security, reliability and more
Diffstat (limited to 'util/tools/r_functions.pl')
| -rwxr-xr-x | util/tools/r_functions.pl | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/util/tools/r_functions.pl b/util/tools/r_functions.pl new file mode 100755 index 0000000..f4834c6 --- /dev/null +++ b/util/tools/r_functions.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Encode; +use AnyEvent; +use AnyEvent::Handle; + +our %S; + +################################################################################ +# Verify whether a given domain name or IP address and port are valid. +# returns the valid ip-address + port, or 0 when not. +################################################################################ +sub valid_address { + my $h = shift; + + # split up address and port + my ($a, $p) = ($h =~ m/:/) ? $h =~ /(.*):(.*)/ : ($h,0); + return (undef,undef) unless ($a && $p); + + # resolve hostname when needed -- shouldn't even be in the list! FIXME + #if($a =~ /[a-zA-Z]/g) { + # my $raw_addr = (gethostbyname($a))[4]; + # my @octets = unpack("C4", $raw_addr); + # $a = join(".", @octets); + #} + + # check if IP and port are in valid range + $a = ($a =~ '\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b') ? $a : 0; + $p = (0 < $p && $p <= 65535) ? $p : 0; + + # exclude addresses where we don't want people sniffing + for (qw|192.168.(.\d*).(.\d*) 127.0.(.\d*).(.\d*) 10.0.(.\d*).(.\d*)|){$a = 0 if ($a =~ m/$_/)} + + return ($a, $p); +} + +sub query_master { + my $ms = shift; + + for my $g (@{$ms->{games}}) { + + my $cv = AnyEvent->condvar; + my $master_list = ""; + my $handle; $handle = new AnyEvent::Handle( + connect => [$ms->{ip} => $ms->{port}], + timeout => 15, + poll => 'r', + on_error => sub { + print "($ms->{ip}, $g) $!\n"; + $handle->destroy; + $cv->send; + }, + on_eof => sub { + process_received_data($master_list, $g, $ms); + $handle->destroy; + $cv->send; + }, + on_read => sub { + my $m = $_[0]->rbuf; + $_[0]->rbuf = ""; + + # part 1: receive \basic\\secure\$key + if ($m =~ m/\\basic\\\\secure\\/) { + + # received data + my %r; + $m =~ s/\\([^\\]+)\\([^\\]+)/$r{$1}=$2/eg; + + # respond to challenge + my $validate = get_validate_string($S{game}->{$g}->{key}, $r{secure}, $r{enctype}||0); + + # print and send response + $handle->push_write("\\gamename\\$g\\location\\0\\validate\\$validate\\final\\"); + + #part 3: also request the list \list\gamename\ut -- skipped in UCC applets + $handle->push_write("\\list\\\\gamename\\$g\\final\\"); + } + + # part 3b: receive the entire list in multiple steps. + if ($m =~ m/\\ip\\/) { $master_list .= $m; } + } + ); + $cv->recv; + } +} + +sub process_received_data { + my ($buf, $g, $ms) = @_; + $buf = encode('UTF-8', $buf); + + #counter + my $c = 0; + + # parse $buf into an array of [ip, port] + foreach my $l (split(/\\/, $buf)) { + + # search for \ip\255.255.255.255:7778\, contains ':' + if ($l =~ /:/) { + my ($a,$p) = valid_address($l); + next unless ($a && $p); + db_add_server(ip => $a, port => $p); + $c++; + } + } + + print "found $c \t$g \taddresses at $ms->{ip}.\n" if ($c > 0 ); +} + +1; |
