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
|
package MasterServer::TCP::UCCAppletQuery;
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use Exporter 'import';
our @EXPORT = qw| query_applet |;
################################################################################
## The UCC Applet (Epic Megagames, Inc.) functions as a master server for one
## single game. However, it does not always follow the defined protocol.
## This module connects with UCC masterserver applets to receive the list.
################################################################################
sub query_applet {
my ($self, $ms) = @_;
# be nice to notify
$self->log("tcp","start querying $ms->{ip}:$ms->{port} for '$ms->{game}' games");
# list to store all IPs in.
my $master_list = "";
# connection handle
my $handle;
$handle = new AnyEvent::Handle(
connect => [$ms->{ip} => $ms->{port}],
timeout => 5,
poll => 'r',
on_error => sub {$self->error($!, "$ms->{ip}:$ms->{port}"); $handle->destroy;},
on_eof => sub {$self->process_ucc_applet_query($master_list, $ms); $handle->destroy;},
on_read => sub {
# receive and clear buffer
my $m = $_[0]->rbuf;
$_[0]->rbuf = "";
# remove string terminator
chop $m if $m =~ m/secure/;
# 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 = $self->validate_string(gamename => $ms->{game},
enctype => $r{enctype}||0,
secure => $r{secure});
# send response
$handle->push_write("\\gamename\\$ms->{game}\\location\\0\\validate\\$validate\\final\\");
# part 3: also request the list \list\gamename\ut -- skipped in UCC applets
$handle->push_write("\\list\\\\gamename\\$ms->{game}\\final\\");
}
# part 3b: receive the entire list in multiple steps.
if ($m =~ m/\\ip\\/) {
# add buffer to the list
$master_list .= $m;
}
}
);
}
1;
|