aboutsummaryrefslogtreecommitdiff
path: root/lib/MasterServer/TCP/UCCAppletQuery.pm
diff options
context:
space:
mode:
authorDarkelarious <darkelarious@333networks.com>2016-11-19 20:56:04 +0100
committerDarkelarious <darkelarious@333networks.com>2016-11-19 20:56:04 +0100
commitc3f8d65a4fb1f5674557ee67cf7f74369df86ad1 (patch)
tree92aab2a394bda28da0ed7c7c75e633fdf386fc71 /lib/MasterServer/TCP/UCCAppletQuery.pm
parent1de3da4b8027508a91144639455c934fd6ccb9b7 (diff)
downloadMasterServer-Perl-c3f8d65a4fb1f5674557ee67cf7f74369df86ad1.tar.gz
MasterServer-Perl-c3f8d65a4fb1f5674557ee67cf7f74369df86ad1.zip
Massive improvements on efficiency, robustness, security, reliability and more
Diffstat (limited to 'lib/MasterServer/TCP/UCCAppletQuery.pm')
-rwxr-xr-xlib/MasterServer/TCP/UCCAppletQuery.pm72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/MasterServer/TCP/UCCAppletQuery.pm b/lib/MasterServer/TCP/UCCAppletQuery.pm
new file mode 100755
index 0000000..e3eb587
--- /dev/null
+++ b/lib/MasterServer/TCP/UCCAppletQuery.pm
@@ -0,0 +1,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->log("error", "$! on $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;