aboutsummaryrefslogtreecommitdiff
path: root/util/tools/r_functions.pl
blob: f4834c6d21a4fd352e13137675717949233b43c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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;