aboutsummaryrefslogtreecommitdiff
path: root/lib/MasterServer/UDP/UCCAppletQuery.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MasterServer/UDP/UCCAppletQuery.pm')
-rwxr-xr-xlib/MasterServer/UDP/UCCAppletQuery.pm85
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/MasterServer/UDP/UCCAppletQuery.pm b/lib/MasterServer/UDP/UCCAppletQuery.pm
new file mode 100755
index 0000000..bd7bb73
--- /dev/null
+++ b/lib/MasterServer/UDP/UCCAppletQuery.pm
@@ -0,0 +1,85 @@
+
+package MasterServer::UDP::UCCAppletQuery;
+
+use strict;
+use warnings;
+use AnyEvent;
+use AnyEvent::Handle;
+use Exporter 'import';
+
+our @EXPORT = qw| ucc_applet_query_scheduler query_applet |;
+
+################################################################################
+## Query other UCC applets periodically to get a list of online servers.
+################################################################################
+sub ucc_applet_query_scheduler {
+ my $self = shift;
+ $self->log("load", "UCC Applet Query Scheduler is loaded.");
+
+ my $i = 0;
+ return AnyEvent->timer (
+ after => $self->{master_applet_time}[0],
+ interval => $self->{master_applet_time}[1],
+ cb => sub {
+ # check if there's a master server entry to be queried. If not, return
+ # to zero and go all over again.
+ $i = 0 unless $self->{master_applet}[$i];
+ return if (!defined $self->{master_applet}[$i]);
+
+ # perform the query
+ $self->query_applet($self->{master_applet}[$i]);
+
+ #increment counter
+ $i++;
+ }
+ );
+}
+
+################################################################################
+## 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("applet","[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\\/) {
+ # skip to part 3: also request the list \list\gamename\ut
+ #$handle->push_write("\\list\\\\gamename\\$ms->{game}");
+ $handle->push_write("\\list\\");
+ }
+
+ # part 3b: receive the entire list in multiple steps.
+ if ($m =~ m/\\ip\\/) {
+ # add buffer to the list
+ $master_list .= $m;
+ }
+ }
+ );
+}
+
+1;