diff options
| author | Darkelarious <darkelarious@333networks.com> | 2015-02-10 18:22:08 +0100 |
|---|---|---|
| committer | Darkelarious <darkelarious@333networks.com> | 2015-02-10 18:22:08 +0100 |
| commit | e0ada80f8582cf3b28e70b8f18de10aa505159ae (patch) | |
| tree | 2b018677902d0d603bd1feb076153f6e7c68d75e /lib/MasterServer/UDP/BeaconChecker.pm | |
| parent | 5057ec47aa9a1702b2483e0a0b3ba325bb0b7abb (diff) | |
| download | MasterServer-Perl-e0ada80f8582cf3b28e70b8f18de10aa505159ae.tar.gz MasterServer-Perl-e0ada80f8582cf3b28e70b8f18de10aa505159ae.zip | |
Postgresql beacon receiving procedure complete and working
Diffstat (limited to 'lib/MasterServer/UDP/BeaconChecker.pm')
| -rwxr-xr-x | lib/MasterServer/UDP/BeaconChecker.pm | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/lib/MasterServer/UDP/BeaconChecker.pm b/lib/MasterServer/UDP/BeaconChecker.pm new file mode 100755 index 0000000..5fc2b38 --- /dev/null +++ b/lib/MasterServer/UDP/BeaconChecker.pm @@ -0,0 +1,180 @@ + +package MasterServer::UDP::BeaconChecker; + +use strict; +use warnings; +use Encode; +use AnyEvent::Handle::UDP; +use Exporter 'import'; + +our @EXPORT = qw| beacon_checker query_udp_server|; + +################################################################################ +## +## Beacon Checker Module +## +## When addresses are stored in the 'pending' list, they are supposed to be +## queried immediately with the secure/validate challenge to testify that +## the server is genuine and alive. +## +## Some servers do not support the secure-challenge on the Uplink port. These +## servers are verified with a secure-challenge on their heartbeat ports, +## which are designed to respond to secure queries, as well as status queries. +## +## Querying pending servers should only happen when beacons are already +## several seconds old. We do not want to interfere with the existing +## construction where servers respond immediately. +## +## Addresses collected by other scripts, whether from the UCC applet or manual +## input via the website, are added to the pending query table. It is more +## important to verify pending beacons and new server addresses, than to +## update the status of existing addresses. Therefore, pending addresses are +## prioritized. +## +################################################################################ +sub beacon_checker { + my $self = shift; + $self->log("load", "UDP Beacon Checker is loaded."); + + # queue -- which address is next in line? + my %q = ( pending_id => 0, + server_id => 0, + start_time => time+$self->{beacon_checker_time}[0]-1, #time+grace + ); + + # go through all servers one by one, new and old + my $server_info = AnyEvent->timer ( + after => $self->{beacon_checker_time}[0], + interval => $self->{beacon_checker_time}[1], + cb => sub { + + # first of all, check whether we exceeded our time cap limit + if ( (time - $q{start_time}) >= $self->{beacon_checker_time}[2] ){ + # reset queue variables + $q{pending_id} = 0; + $q{server_id} = 0; + $q{start_time} = time; + } + + # id, ip, port reference of the server to be queried + my $n; + + # + # Pending Servers + # + # See if there are pending servers, and use existing secure string for + # the challenge. + $n = $self->get_next_pending($q{pending_id}); + + # if any entries were found, proceed + if ( $n->[0] ) { + + # next pending id will be > $n + $q{pending_id} = $n->[0]; + + # query the server + $self->query_udp_server($n->[1], $n->[2], $n->[3]); + + # work done. Wait for the next round for the next task. + return; + } + + # if no pending servers left, update the other entries + $n = $self->get_next_server($q{server_id}); + + # if any entries were found, proceed + if ( $n->[0] ) { + + # next server id will be > $n + $q{server_id} = $n->[0]; + + # query the server + $self->query_udp_server($n->[1], $n->[2], ""); + + # work done. Wait for the next round for the next task. + return; + } + + # At this point, we are out of server entries. When new servers are + # added, they are immediately queried on the next round. + # From here on, just count down until the cycle is complete. + + # DEBUG (spams badly) + $self->log("debug_spam", "Checker timer: t=".(time - $q{start_time})); + } + ); + + $self->log("info", "Verifying servers every $self->{beacon_checker_time}[2] seconds."); + + # return the timer to keep it alive outside of scope + return $server_info; +} + + +################################################################################ +## +## UDP Server Query function +## +## Get the server status from any server over UDP and store the +## received information in the database. +## +## $secure determines the type of query: secure/pending or information +## +## Args: $ip, $port, payload +## Function is called by AnyEvent->timer() above +################################################################################ +sub query_udp_server { + my ($self, $ip, $port, $secure) = @_; + my $buf = ""; + + # debug spamming + $self->log("debug_spam", "Query server $ip:$port"); + + # connect with UDP server + my $udp_client; $udp_client = AnyEvent::Handle::UDP->new( + # Bind to this host and port + connect => [$ip, $port], + timeout => 1, + on_timeout => sub {$udp_client->destroy();}, # don't bother reporting timeouts + on_error => sub {$udp_client->destroy();}, # or errors + on_recv => sub { + + # add packet to buffer + $buf .= $_[0]; + + # if validate, assume that we sent a \basic\secure request. + if ($buf =~ m/\\validate\\/){ + $self->process_udp_validate($buf, $ip, undef, $port); + } + # if gamename, ver, hostname and hostport are available, it should have been \basic\info + elsif ($buf =~ m/\\gamename\\/ && $buf =~ m/\\gamever\\/ + && $buf =~ m/\\hostname\\/ && $buf =~ m/\\hostport\\/) { + $self->process_query_response($buf, $ip, $port); + } + # else partial information received. wait for more. + else{ } + }, + ); + + # + # Send secure message or status, depending on provided variables + # + + # secure servers enabled and secure key provided + if ($secure ne "" && $self->{require_secure_beacons} > 0) { + # send secure + $udp_client->push_send("\\basic\\\\secure\\$secure"); + + # and log that we sent it + $self->log("udp", "sending secure=\"$secure\" to $ip:$port"); + } + else { + # send information request + $udp_client->push_send("\\basic\\\\info\\"); + + # and log that we sent it + $self->log("udp","sending basic request to $ip:$port"); + } +} + +1; |
