aboutsummaryrefslogtreecommitdiff
path: root/lib/MasterServer/TCP/Syncer.pm
diff options
context:
space:
mode:
authorDarkelarious <darkelarious@333networks.com>2017-08-22 11:00:13 +0200
committerDarkelarious <darkelarious@333networks.com>2017-08-22 11:00:13 +0200
commitc06322da38b4cb76b2036af1a5448083adb8ff20 (patch)
tree189c9f0fec3325be927f763aba23cf18aa68cfe4 /lib/MasterServer/TCP/Syncer.pm
parente0d727670cbeda0db0812c5c9efc503d75f8d0a4 (diff)
downloadMasterServer-Perl-2.4.0.tar.gz
MasterServer-Perl-2.4.0.zip
new server checking mechanism, complete recode of major functionsv2.4.0
Diffstat (limited to 'lib/MasterServer/TCP/Syncer.pm')
-rwxr-xr-xlib/MasterServer/TCP/Syncer.pm226
1 files changed, 115 insertions, 111 deletions
diff --git a/lib/MasterServer/TCP/Syncer.pm b/lib/MasterServer/TCP/Syncer.pm
index d890f00..cf7ee5b 100755
--- a/lib/MasterServer/TCP/Syncer.pm
+++ b/lib/MasterServer/TCP/Syncer.pm
@@ -5,152 +5,156 @@ use warnings;
use AnyEvent;
use AnyEvent::Handle;
use Exporter 'import';
-
-our @EXPORT = qw| sync_with_master
- process_sync_list |;
+our @EXPORT = qw| synchronize
+ process_applet
+ process_syncer |;
################################################################################
-## Sends synchronization request to another 333networks based master server and
-## receives the list of games.
+## Synchronize with UCC Applets (Epic Megagames, Inc.) or other 333networks
+## based masterservers.
################################################################################
-sub sync_with_master {
- my ($self, $ms) = @_;
-
- # announce
- $self->log("tcp", "Attempting to synchronize with $ms->{ip}");
+sub synchronize {
+ my ($self, $ms, $type) = @_;
+ my $ipbuflist = "";
- # list to store all IPs in.
- my $sync_list = "";
-
# connection handle
- my $handle;
- $handle = new AnyEvent::Handle(
+ my $handle; $handle = new AnyEvent::Handle(
connect => [$ms->{ip} => $ms->{hostport}],
timeout => $self->{timeout_time},
poll => 'r',
- on_error => sub {$self->error($!, "$ms->{ip}:$ms->{hostport}"); $handle->destroy;},
- on_eof => sub {$self->process_sync_list($sync_list, $ms); $handle->destroy;},
+ on_error => sub {$handle->destroy; $self->error($!, "$ms->{ip}:$ms->{hostport}");},
+ on_eof => sub {
+ $handle->destroy;
+ if ($type eq "applet") {$self->process_applet($ipbuflist, $ms);}
+ if ($type eq "333nwm") {$self->process_syncer($ipbuflist, $ms);}
+ },
on_read => sub {
-
# receive and clear buffer
my $m = $_[0]->rbuf;
$_[0]->rbuf = "";
- # remove string terminator: sometimes trailing slashes, line endings or
- # string terminators are added or forgotten by sender, so \secure\abcdef
- # is actually \secure\abcdef{\0}
- chop $m if $m =~ m/secure/;
-
# part 1: receive \basic\\secure\$key
- if ($m =~ m/basic\\\\secure/) {
+ if ($m =~ m/\\basic\\\\secure\\/) {
- # hash $m into %r
- my %r = ();
- $m =~ s/\\\\/\\undef\\/;
- $m =~ s/\n//;
- $m =~ s/\\([^\\]+)\\([^\\]+)/$r{$1}=$2/eg;
+ # use provided gamename for applet or 333networks for syncer
+ my $gamename = "";
+ $gamename = $ms->{gamename} if ($type eq "applet");
+ $gamename = "333networks" if ($type eq "333nwm");
- # respond to the validate challenge
+ # processess received data and respond to challenge
+ my $rx = $self->data2hashref($m);
my $validate = $self->validate_string(
- gamename => "333networks",
- secure => $r{secure},
- enctype => $r{enctype}
- );
+ gamename => $gamename,
+ enctype => $rx->{enctype},
+ secure => $rx->{secure}
+ );
+
+ # send challenge response
+ $handle->push_write("\\gamename\\$gamename\\location\\0\\validate\\$validate\\final\\");
+
+ # part 3a: also request the list \list\\gamename\ut
+ my $request = "";
+ if ($type eq "applet") {
+ $request = "\\list\\\\gamename\\$ms->{gamename}\\final\\";}
+ # part 3b: request the list \sync\[gamenames] consisting of space-seperated game names or "all"
+ if ($type eq "333nwm") {
+ $request = "\\sync\\".($self->{sync_games}[0] == 0 ? "all" : $self->{sync_games}[1] )."\\final\\";}
- # part 2: send \gamename\ut\location\0\validate\$validate\final\
- $handle->push_write("\\gamename\\333networks\\location\\0\\validate\\$validate\\final\\");
-
- # part 3: request the list \sync\gamenames consisting of space-seperated game names or "all"
- # compatibility note: old queries use "new", instead treat them as "all".
- my $request = "\\sync\\"
- . (($self->{sync_games}[0] == 0) ? ("all") : $self->{sync_games}[1])
- . "\\final\\";
-
# push the request to remote host
$handle->push_write($request);
-
- # clean up $m for future receivings
- $m = "";
-
- } # end secure
+ }
- # part 4: receive the entire list in multiple steps
- $sync_list .= $m;
- },
+ # part 4: receive the entire list in multiple steps.
+ # continue receiving data and adding to the buffer
+ else {$ipbuflist .= $m;}
+ }
);
}
################################################################################
-## Process the list of addresses that was received after querying the UCC applet
-## and store them in the pending list.
+## Process the list of addresses received from the UCC applet masterserver and
+## move new addresses to the pending list.
################################################################################
-sub process_sync_list {
- my ($self, $m, $ms) = @_;
-
- # replace empty values for the string "undef" and replace line endings from netcatters
- # parse hash {gamename => list of ips seperated by space}
- my %r = ();
- $m =~ s/\\\\/\\undef\\/;
- $m =~ s/\n//;
- $m =~ s/\\([^\\]+)\\([^\\]+)/$r{$1}=$2/eg;
+sub process_applet {
+ my ($self, $buf, $ms) = @_;
+ my $new = 0; my $tot = 0;
+
+ # database types such as SQLite are slow, therefore use transactions.
+ $self->{dbh}->begin_work;
+
+ # parse $buf into an array of [ip, port]
+ foreach my $l (split /\\/, $buf) {
+
+ # search for \ip\255.255.255.255:7778\ and capture ip and port
+ if (my ($address,$port) = $l =~ /([\.\w]+):(\d+)/ ) {
+ # check if address entry is valid
+ if ($self->valid_address($address,$port)) {
+
+ # add server and count new/total addresses
+ $new += $self->insert_pending(ip => $address, port => $port);
+ $tot++;
+ }
+ # invalid address, log
+ else {$self->log("error", "invalid address found at $ms->{ip}:$ms->{hostport} > $l (applet)");}
+ }
+ } # end foreach
- # counter
- my $c = 0;
+ # complete transaction
+ $self->{dbh}->commit;
+
+ # update time if successful applet query
+ $self->update_master_applet(ip => $ms->{ip}, port => $ms->{hostport}, gamename => $ms->{gamename} )
+ if ($tot > 0);
+
+ # print findings
+ $self->log("syncer","found $tot ($new new) addresses at $ms->{ip},$ms->{hostport} for $ms->{gamename} (applet)");
+}
+
+################################################################################
+## Process the list of addresses received from the 333networks masterserver and
+## move new addresses to the pending list.
+################################################################################
+sub process_syncer {
+ my ($self, $buf, $ms) = @_;
+ my $new = 0; my $tot = 0;
+
+ # extract to hash: gamename => ( address list )
+ my $rx = $self->data2hashref($buf);
- if (exists $r{echo}) {
- # remote address says...
- $self->log("echo", "$ms->{ip} replied: $r{echo}");
- }
+ # use transactions for large numbers of ip/ports
+ $self->{dbh}->begin_work;
# iterate through the gamenames and addresses
- while ( my ($gn,$addr) = each %r) {
-
- # process all games wether we have a cipher for them.
- if (defined $gn) {
-
- # some database types, such as SQLite, are slow - therefore use transactions.
- $self->{dbh}->begin_work;
-
- # l(ocations, \label\ip:port\) split up in a(ddress) and p(ort)
- foreach my $l (split(/ /, $addr)) {
-
- # search for \255.255.255.255:7778\, contains ':'
- if ($l =~ /:/) {
- my ($a,$p) = $l =~ /(.*):(.*)/;
-
- # check if address entry is valid
- if ($self->valid_address($a,$p)) {
- # count number of valid addresses
- $c++;
-
- # add server
- $self->syncer_add($a, $p, $gn, $self->secure_string());
-
- # print address (debug)
- # $self->log("add", "syncer added $gn\t$a\t$p");
- }
- else {
- # invalid address, log
- $self->log("error", "invalid address found while syncing at $ms->{ip}: $l!");
- }
-
- } # endif ($l =~ /:/)
- } # end for / /
-
- # end transaction, commit
- $self->{dbh}->commit;
+ while ( my ($gamename,$addresslist) = each %{$rx}) {
+
+ # parse $buf into an array of [ip, port]
+ foreach my $l (split / /, $addresslist) {
+
+ # search for \ip\255.255.255.255:7778\ and capture ip and port
+ if (my ($address,$port) = $l =~ /([\.\w]+):(\d+)/ ) {
- } # end defined $gn
+ # check if address entry is valid
+ if ($self->valid_address($address,$port)) {
+ # add server and count new/total addresses
+ $new += $self->insert_pending(ip => $address, port => $port);
+ $tot++;
+
+ }
+ # invalid address, log
+ else {$self->log("error", "invalid address found at $ms->{ip}:$ms->{hostport} > $l (333nwm)");}
+ }
+ } # end foreach
} # end while
- # update this sync master in the gamelist with lastseen time
- $self->update_server_list(
- ip => $ms->{ip},
- port => $ms->{port},
- ) if ($c > 0);
+ # complete transaction
+ $self->{dbh}->commit;
+
+ # update time if successful sync master query
+ $self->update_server(ip => $ms->{ip}, hostport => $ms->{hostport})
+ if ($tot > 0);
# end message
- $self->log("sync-rx", "received $c addresses after syncing from $ms->{ip}:$ms->{hostport}");
+ $self->log("syncer", "found $tot ($new new) addresses at $ms->{ip},$ms->{hostport} (333nwm)");
}
1;