diff options
| author | Darkelarious <darkelarious@333networks.com> | 2017-08-22 11:00:13 +0200 |
|---|---|---|
| committer | Darkelarious <darkelarious@333networks.com> | 2017-08-22 11:00:13 +0200 |
| commit | c06322da38b4cb76b2036af1a5448083adb8ff20 (patch) | |
| tree | 189c9f0fec3325be927f763aba23cf18aa68cfe4 /lib/MasterServer/TCP | |
| parent | e0d727670cbeda0db0812c5c9efc503d75f8d0a4 (diff) | |
| download | MasterServer-Perl-c06322da38b4cb76b2036af1a5448083adb8ff20.tar.gz MasterServer-Perl-c06322da38b4cb76b2036af1a5448083adb8ff20.zip | |
new server checking mechanism, complete recode of major functionsv2.4.0
Diffstat (limited to 'lib/MasterServer/TCP')
| -rwxr-xr-x | lib/MasterServer/TCP/BrowserHost.pm | 78 | ||||
| -rwxr-xr-x | lib/MasterServer/TCP/Handler.pm | 211 | ||||
| -rwxr-xr-x | lib/MasterServer/TCP/ListCompiler.pm | 133 | ||||
| -rwxr-xr-x | lib/MasterServer/TCP/Syncer.pm | 226 | ||||
| -rwxr-xr-x | lib/MasterServer/TCP/UCCAppletQuery.pm | 72 |
5 files changed, 213 insertions, 507 deletions
diff --git a/lib/MasterServer/TCP/BrowserHost.pm b/lib/MasterServer/TCP/BrowserHost.pm index c53ae42..316a135 100755 --- a/lib/MasterServer/TCP/BrowserHost.pm +++ b/lib/MasterServer/TCP/BrowserHost.pm @@ -5,59 +5,89 @@ use warnings; use AnyEvent::Socket; use AnyEvent::Handle; use Exporter 'import'; +our @EXPORT = qw| browser_host |; -our @EXPORT = qw| browser_host clean_tcp_handle|; +# keep handle alive and store authentication info +my %conn = (); ################################################################################ ## wait for incoming TCP connections from game clients and other masterservers. -## respond with secure/validate, contact info and/or server lists. +## respond with secure/validate and/or server lists. ## allow other masterservers to synchronize ################################################################################ sub browser_host { my $self = shift; my $browser = tcp_server undef, $self->{listen_port}, sub { - my ($fh, $a, $p) = @_; - - # validated? yes = 1 no = 0 + my ($fh, $addr, $port) = @_; my $auth = 0; - # debug -- new connection opened - #$self->log("tcp","New connection from $a:$p"); - - # prep a challenge + # prepare a secure/validate challenge my $secure = $self->secure_string(); - - # handle received data - my $h; $h = AnyEvent::Handle->new( + + # handle for client connection + my $client; $client = AnyEvent::Handle->new( fh => $fh, poll => 'r', timeout => $self->{timeout_time}, - on_eof => sub {$self->log("tcp","eof on $a:$p" ); $self->clean_tcp_handle(@_)}, - on_error => sub {$self->error($!, "browser $a:$p"); $self->clean_tcp_handle(@_)}, - on_read => sub {$self->read_tcp_handle($h, $a, $p, $secure, @_)}, + on_eof => sub {drop_handle($client);}, + on_error => sub {drop_handle($client);$self->error($!, "client $addr:$port");}, + on_read => sub { + # receive data + my $rx = $self->data2hashref($client->rbuf);$client->rbuf = ""; + + # Support echo: log, but don't respond (or recursive echo abuse) + $self->log("echo","msg $addr:$port: $rx->{echo}") if $rx->{echo}; + + # first check for validation info + if ($rx->{validate} && $rx->{gamename}) { + $auth = $self->auth_browser( + gamename => $rx->{gamename}, + secure => $secure, + enctype => $rx->{enctype}, + validate => $rx->{validate}, + ); + $conn{$client}[1] = $auth; + $self->log("secure", "client $addr:$port failed validation $rx->{gamename}") unless $auth;} + + # list request with valid gamename / challenge + if ($auth && $rx->{gamename} && exists $rx->{list}) { + $client->push_write($self->generate_list($rx->{gamename}, $rx->{list})."\\final\\"); + $self->log("list","$addr:$port retrieved the list for $rx->{gamename}"); + drop_handle($client)} + + # sync request with valid gamename / challenge + if ($auth && $rx->{sync}) { + $client->push_write($self->generate_sync($rx->{sync})."\\final\\"); + $self->log("syncer","$addr:$port synchronized $rx->{sync}"); + drop_handle($client)} + + # request without valid gamename and/or authentication + if (!$auth && ($rx->{sync} || exists $rx->{list}) ) { + $client->push_write("\\echo\\You failed to authenticate. See 333networks.com for more info.\\final\\"); + $self->log("warning","$addr:$port failed to authenticate before requesting a list/sync"); + drop_handle($client);} + }, ); # part 1: send \basic\\secure\$key\ - $h->push_write("\\basic\\\\secure\\$secure\\final\\"); + $client->push_write("\\basic\\\\secure\\$secure\\final\\"); - # keep handle alive longer and store authentication info - $self->{browser_clients}->{$h} = [$h, $auth]; - return; + # keep handle alive and store authentication info + $conn{$client} = [$client, $auth]; }; # startup of TCP server complete - $self->log("info", "Listening for TCP connections on port $self->{listen_port}."); + $self->log("info", "listening for TCP connections on port $self->{listen_port}"); return $browser; } ################################################################################ ## clean handles on timeouts, completed requests and/or errors ################################################################################ -sub clean_tcp_handle{ - my ($self, $c) = @_; - # clean and close the connection - delete ($self->{browser_clients}->{$c}); +sub drop_handle { + my $c = shift; + delete $conn{$c}; $c->destroy(); } diff --git a/lib/MasterServer/TCP/Handler.pm b/lib/MasterServer/TCP/Handler.pm deleted file mode 100755 index eb0094d..0000000 --- a/lib/MasterServer/TCP/Handler.pm +++ /dev/null @@ -1,211 +0,0 @@ -package MasterServer::TCP::Handler; - -use strict; -use warnings; -use AnyEvent::Socket; -use AnyEvent::Handle; -use Exporter 'import'; - -our @EXPORT = qw| read_tcp_handle - handle_validate - handle_list - handle_sync |; - -################################################################################ -## wait for incoming TCP connections from game clients and other masterservers. -## respond with secure/validate, contact info and/or server lists. -## allow other masterservers to synchronize -################################################################################ -sub read_tcp_handle { - my ($self, $h, $a, $p, $secure, $c) = @_; - - # clear the buffer - my $m = $c->rbuf; - $c->rbuf = ""; - - # did the client validate already? - my $val = $self->{browser_clients}->{$h}[1]; - - # in case of errors, log the original message - my $rxbuf = $m; - #$self->log("debug","$a:$p sent $rxbuf"); - - # allow multiple blocks to add to the response string - my $response = ""; - - # replace empty values for the string "undef" and replace line endings from netcatters - # parse the received data and extrapolate all the query commands found - my %r = (); - $m =~ s/\\\\/\\undef\\/; - $m =~ s/\\$/\\undef\\/; - $m =~ s/\\([^\\]+)\\([^\\]+)/$r{$1}=$2/eg; - - # secure/validate challenge - # part 2: receive \gamename\ut\location\0\validate\$validate\final\ - $val = $self->handle_validate(\%r, $h, $secure, $a, $p) - if (exists $r{validate} && !$val); - - # return address list - # part 3: wait for the requested action: \list\\gamename\ut\ - $self->handle_list($val, \%r, $c, $a, $p) if (exists $r{list} && exists $r{gamename}); - - # Sync request from another 333networks-based masterserver. Respond with list - # of requested games (or all games). - $self->handle_sync($val, \%r, $c, $a, $p) if (exists $r{sync}); - - # - # Support echo: doesn't do anything but print to log if not suppressed. - $self->log("echo","($a:$p): $r{echo}") if $r{echo}; - - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # improper syntax/protocol -- no valid commands found - # respond with an error. - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - if ("sync validate list" =~ m/\Q$response\E/i) { - - # error message to client - $c->push_write("\\echo\\333networks did not understand your request. ". - "Contact us via 333networks.com\\final\\"); - - # and log it - $self->log("error","invalid request from browser $a:$p with unknown message \"$rxbuf\"."); - } # end if weird query - else { - $c->push_write($response . "\\final\\") if ($response ne ""); - } -} - -################################################################################ -## The master server opens the connection with the \secure\ challenge. The -## client should respond with basic information about itself and the -## \validate\ response. In this code block we verify the challenge/response. -################################################################################ -sub handle_validate { - my ($self, $r, $h, $secure, $a, $p) = @_; - - # auth var init - my $val = 0; - - # pass or fail the secure challenge - if (exists $r->{gamename} && $self->get_game_props(gamename => $r->{gamename})) { - - # game exists and we have the key to verify the response - $val = $self->compare_challenge( - gamename => $r->{gamename}, - secure => $secure, - enctype => $r->{enctype}, - validate => $r->{validate}, - ignore => $self->{ignore_browser_key}, - ); - - # update for future queries - $self->{browser_clients}->{$h}[1] = $val; - } - elsif (exists $r->{gamename}) { - # log - $self->log("support", "received unknown gamename request \"$r->{gamename}\" from $a:$p."); - } - - # log (debug) - #$self->log("secure","$a:$p validated with $val for $r->{gamename}, $secure, $r->{validate}"); - - # return auth status - return $val; -} - -################################################################################ -## At this point, the client should be validated and ready to request with -## the \secure\ command and is allowed to ask for the list. -################################################################################ -sub handle_list { - my ($self, $val, $r, $c, $a, $p) = @_; - - # confirm validation - if ($val && exists $r->{gamename}) { - - # prepare the list - my $data = ""; - - # determine the return format - if ($r->{list} =~ /^cmp$/i) { - # return addresses as byte format (ip=ABCD port=EF) - $data .= $self->compile_list_cmp($r->{gamename}); - } - else { - # return addresses as regular \ip\127.0.0.1:7777\ format - $data .= $self->compile_list($r->{gamename}); - } - - # finalize response string - $data .= "\\final\\"; - - # immediately send to client - $c->push_write($data); - - # log successful - $self->log("list","$a:$p successfully retrieved the list for $r->{gamename}."); - - # clean and close the connection - #$self->log("tcp","closing $a:$p"); - $self->clean_tcp_handle($c); - } - - # proper syntax/protocol, but incorrect validation. Therefore respond with - # an 'empty' list, returning only \final\. - else { - # return error/empty list - $c->push_write("\\echo\\333networks failed to validate your request. Use the correct authorization cipher!\\final\\"); - - # log it too - $self->log("error","browser $a:$p failed validation for $r->{gamename}"); - - # clean and close the connection - #$self->log("tcp","closing $a:$p"); - $self->clean_tcp_handle($c); - } -} - -################################################################################ -## Respond to \sync\ requests from other 333networks-based masterservers. After -## validation, sync behaves in much the same way as \list\, -################################################################################ -sub handle_sync { - my ($self, $val, $r, $c, $a, $p) = @_; - - # alternate part 3: wait for the requested action: \sync\(all|list of games)\sender\domainname - $self->log("tcp","Sync request from $a:$p found."); - - if ($val && exists $r->{sync}) { - - # compile list of addresses - my $data = $self->compile_sync($r->{sync}); - $data .= "\\final\\"; - - # send to remote client - $c->push_write($data); - - # log successful (debug) - $self->log("sync-tx","$a:$p successfully synced."); - - # clean and close the connection - #$self->log("tcp","closing $a:$p"); - $self->clean_tcp_handle($c); - - } - # proper syntax/protocol, but incorrect validation. Therefore respond with - # an 'empty' list, returning only \final\. - else { - - # return error/empty list - $c->push_write("\\echo\\333networks failed to validate your request. Use a proper authorization key!\\final\\"); - - # log it too - $self->log("error","$a:$p failed synchronization."); - - # clean and close the connection - #$self->log("tcp","closing $a:$p"); - $self->clean_tcp_handle($c); - } -} - -1; diff --git a/lib/MasterServer/TCP/ListCompiler.pm b/lib/MasterServer/TCP/ListCompiler.pm index c035008..edced5e 100755 --- a/lib/MasterServer/TCP/ListCompiler.pm +++ b/lib/MasterServer/TCP/ListCompiler.pm @@ -3,120 +3,75 @@ package MasterServer::TCP::ListCompiler; use strict; use warnings; use Exporter 'import'; - -our @EXPORT = qw| compile_list compile_list_cmp compile_sync |; +our @EXPORT = qw| generate_list generate_sync compile_sync |; ################################################################################ ## compile the list of \ip\ip:port\ addresses and parse them into the -## plaintext return string. +## plaintext or compressed address string. ################################################################################ -sub compile_list { - my ($self, $gamename) = @_; +sub generate_list { + # gamename and \list\(|cmp) + my ($self, $gamename, $cmp) = @_; # get the list from database my $serverlist = $self->get_server( - updated => 3600, - gamename => $gamename, - ); - - # prepare empty return string - my $response_string = ""; - - # add address as regular \ip\127.0.0.1:7777\ format - for (@{$serverlist}){ - - # append \ip\ip:port to string - $response_string .= "\\ip\\$_->{ip}:$_->{port}"; - } + updated => 3600, + gamename => $gamename, + ); - # return the string with data - return $response_string; -} - -################################################################################ -## compile the list of binary ip:port addresses and parse them into the -## ABCDE return string. -################################################################################ -sub compile_list_cmp { - my ($self, $gamename) = @_; - - # get the list from database - my $serverlist = $self->get_server( - updated => 3600, - gamename => $gamename, - ); - - # prepare empty return string - my $response_string = ""; - - # compile a return string - for (@{$serverlist}){ - - # convert ip address to ABCDEF mode - my ($A, $B, $C, $D) = ($_->{ip} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/); - my ($E, $F) = ($_->{port} >> 8, $_->{port} & 0xFF); - - # print as chr string of 6 bytes long - my $bin = ""; $bin .= (chr $A) . (chr $B) . (chr $C) . (chr $D) . (chr $E) . (chr $F); - - # append to list of addresses - $response_string .= $bin; + my $list = ""; + # which format? + if ($cmp eq "cmp") { + # compressed format (ABCDEF format) + for (@{$serverlist}) { + my ($A, $B, $C, $D) = ($_->{ip} =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/); + my ($E, $F) = ($_->{port} >> 8, $_->{port} & 0xFF); + my $bin = ""; $bin .= (chr $A) . (chr $B) . (chr $C) . (chr $D) . (chr $E) . (chr $F); + $list .= $bin;} } - - # return the string with data - return $response_string; + else { + # normal format (regular \ip\127.0.0.1:7777\ format) + for (@{$serverlist}) { + $list .= "\\ip\\$_->{ip}:$_->{port}";} + } + + # list ready + return $list; } - ################################################################################ -## compile a list of all requested games --or-- if not specified, a list of -## all games +## compile a list of addresses for all available or requested games. +## opts: all | list of games ################################################################################ -sub compile_sync { +sub generate_sync { my ($self, $sync) = @_; - - # prepare empty return string - my $response_string = ""; - my @games; - - # client requests to sync all games + my $list = ""; + my %games = (); + + # prepare list of games + my $avail = $self->get_gamenames(); if ($sync eq "all") { - # get array of gamenames from db - my $sg = $self->get_gamenames(); - for (@{$sg}) {push @games, $_->[0];} - } - # only selected games + # if "all" is requested, check which games we have available + $games{$_->[0]} = 1 for (@{$avail}); } else { - # split request into array - @games = split " ", $sync; - } + # otherwise, see which of the requested addresses match our db + for (@{$avail}) {$games{$_->[0]} = 1 if ($sync =~ m/$_->[0]/i); } } - # only get unique values from array - my %games = map { $_ => 1 } @games; - # get the list for every requested gamename - for my $g (keys %games) { - - # $g is now a gamename -- check if it's supported. Else ignore. - if ($self->get_game_props(gamename => $g)) { + for my $gamename (keys %games) { # get list from database - my $list = $self->get_server( - updated => 7200, - gamename => $g, - ); + my $listref = $self->get_server(gamename => $gamename, updated => 3600); # add all games to string separated by spaces - my $gamestring = ""; - foreach $_ (@{$list}) {$gamestring .= "$_->{ip}:$_->{port} ";} + my $addresses = ""; + foreach (@{$listref}) {$addresses .= "$_->{ip}:$_->{port} ";} # if it contains at least one entry, add the list to the response list - $response_string .= "\\$g\\$gamestring" if (length $gamestring >= 7); - } + $list .= "\\$gamename\\$addresses" if (length $addresses >= 7); } - - # return \gamename\addresses\gamename2\addresses2 list - return $response_string; + # list ready + return $list; } 1; 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; diff --git a/lib/MasterServer/TCP/UCCAppletQuery.pm b/lib/MasterServer/TCP/UCCAppletQuery.pm deleted file mode 100755 index 2c32de9..0000000 --- a/lib/MasterServer/TCP/UCCAppletQuery.pm +++ /dev/null @@ -1,72 +0,0 @@ -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->{gamename}' games"); - - # list to store all IPs in. - my $master_list = ""; - - # connection handle - my $handle; - $handle = new AnyEvent::Handle( - connect => [$ms->{ip} => $ms->{port}], - timeout => $self->{timeout_time}, - 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->{gamename}, - enctype => $r{enctype}||0, - secure => $r{secure}); - - # send response - $handle->push_write("\\gamename\\$ms->{gamename}\\location\\0\\validate\\$validate\\final\\"); - - # part 3: also request the list \list\gamename\ut -- skipped in UCC applets - $handle->push_write("\\list\\\\gamename\\$ms->{gamename}\\final\\"); - - } - - # part 3b: receive the entire list in multiple steps. - # $m contains \ip\ or part of that string - else { - # add buffer to the list - $master_list .= $m; - } - } - ); -} - -1; |
