use Carp;
use strict;
-use vars qw($me $pc11_max_age $pc11_dup_age $pc23_dup_age
- %spotdup %wwvdup $last_hour %pings %rcmds
+use vars qw($me $pc11_max_age $pc23_max_age $pc11_dup_age $pc23_dup_age
+ %spotdup %wwvdup $last_hour %pings %rcmds
%nodehops @baddx $baddxfn $pc12_dup_age
- %anndup $allowzero);
+ %anndup $allowzero $pc12_dup_lth $decode_dk0wcy);
$me = undef; # the channel id for this cluster
+$decode_dk0wcy = undef; # if set use this callsign to decode announces from the EU WWV data beacon
$pc11_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc11
+$pc23_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc23
$pc11_dup_age = 24*3600; # the maximum time to keep the spot dup list for
$pc23_dup_age = 24*3600; # the maximum time to keep the wwv dup list for
-$pc12_dup_age = 24*3600; # the maximum time to keep the ann dup list for
+$pc12_dup_age = 12*3600; # the maximum time to keep the ann dup list for
+$pc12_dup_lth = 72; # the length of ANN text to save for deduping
%spotdup = (); # the pc11 and 26 dup hash
%wwvdup = (); # the pc23 and 27 dup hash
%anndup = (); # the PC12 dup hash
my ($pcno) = $field[0] =~ /^PC(\d\d)/; # just get the number
return unless $pcno;
return if $pcno < 10 || $pcno > 51;
-
+
+ # dump bad protocol messages unless it is a PC29
+ if ($line =~ /\%[0-9A-F][0-9A-F]/o && $pcno != 29) {
+ dbg('chan', "CORRUPT protocol message - dumped");
+ return;
+ }
+
# local processing 1
my $pcr;
eval {
# store it away
my $spotter = $field[6];
- $spotter =~ s/-\d+$//o; # strip off the ssid from the spotter
+ $spotter =~ s/-[\@\d]+$//o; # strip off the ssid from the spotter
# do some de-duping
my $freq = $field[1] - 0;
dbg('chan', "Bad DX spot, ignored");
return;
}
+
+ # are any of the crucial fields invalid?
+ if ($field[2] =~ /[a-z]/ || $field[6] =~ /[a-z]/ || $field[7] =~ /[a-z]/) {
+ dbg('chan', "Spot contains lower case callsigns, rejected");
+ return;
+ }
my @spot = Spot::add($freq, $field[2], $d, $text, $spotter, $field[7]);
}
if ($pcno == 12) { # announces
- # announce duplicate checking
- my $text = uc unpad($field[3]);
+ # announce duplicate checking
+ my $text = substr(uc unpad($field[3]), 0, $pc12_dup_lth);
my $dupkey = $field[1].$field[2].$text.$field[4].$field[6];
if ($anndup{$dupkey}) {
dbg('chan', "Duplicate Announce ignored\n");
}
$anndup{$dupkey} = $main::systime;
- # global ann filtering
+ # global ann filtering on INPUT
my ($filter, $hops) = Filter::it($self->{annfilter}, @field[1..6], $self->{call} ) if $self->{annfilter};
if ($self->{annfilter} && !$filter) {
dbg('chan', "Rejected by filter");
}
Log('ann', $target, $field[1], $text);
+ if ($decode_dk0wcy && $field[1] eq $decode_dk0wcy) {
+ my ($hour, $k, $next, $a, $r, $sfi, $alarm) = $field[3] =~ /^Aurora Beacon\s+(\d+)UTC,\s+Kiel\s+K=(\d+),.*ed\s+K=(\d+),\s+A=(\d+),\s+R=(\d+),\s+SFI=(\d+),.*larm:\s+(\w+)/;
+ $alarm = ($alarm =~ /^Y/i) ? ', Aurora in DE' : '';
+ my $wwv = Geomag::update($main::systime, $hour, $sfi, $a, $k, "R=$r, Next K=$next$alarm", $decode_dk0wcy, $field[5], $r);
+ }
+
return if $field[2] eq $main::mycall; # it's routed to me
} else {
route($field[2], $line);
# unbusy and stop and outgoing mail (ie if somehow we receive another PC19 without a disconnect)
my $mref = DXMsg::get_busy($call);
- $mref->stop_msg($self) if $mref;
+ $mref->stop_msg($call) if $mref;
# add this station to the user database, if required (don't remove SSID from nodes)
my $user = DXUser->get_current($call);
$user->put;
}
- # queue up any messages
- DXMsg::queue_msg(0) if $self->state eq 'normal';
return if $newline eq "PC19^";
# add hop count
$self->send_local_config();
$self->send(pc22());
$self->state('normal');
-
- # queue mail
- DXMsg::queue_msg(0);
-
return;
}
if ($pcno == 22) {
$self->state('normal');
-
- # queue mail
- DXMsg::queue_msg(0);
return;
}
-
+
if ($pcno == 23 || $pcno == 27) { # WWV info
# route 'foreign' pc27s
my $sfi = unpad($field[3]);
my $k = unpad($field[4]);
my $i = unpad($field[5]);
+ my ($r) = $field[6] =~ /R=(\d+)/;
+ $r = 0 unless $r;
my $dupkey = "$d.$sfi$k$i";
if ($wwvdup{$dupkey}) {
dbg('chan', "Dup WWV Spot ignored\n");
return;
}
- if ($d > $main::systime + 900 || $field[2] < 0 || $field[2] > 23) {
+ if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 900 || $field[2] < 0 || $field[2] > 23) {
dbg('chan', "WWV Date ($field[1] $field[2]) out of range");
return;
}
$wwvdup{$dupkey} = $d;
$field[6] =~ s/-\d+$//o; # remove spotter's ssid
- my $wwv = Geomag::update($d, $field[2], $sfi, $k, $i, @field[6..8]);
+ my $wwv = Geomag::update($d, $field[2], $sfi, $k, $i, @field[6..8], $r);
- my $r;
+ my $rep;
eval {
- $r = Local::wwv($self, $field[1], $field[2], $sfi, $k, $i, @field[6..8]);
+ $rep = Local::wwv($self, $field[1], $field[2], $sfi, $k, $i, @field[6..8], $r);
};
# dbg('local', "Local::wwv2 error $@") if $@;
- return if $r;
+ return if $rep;
# DON'T be silly and send on PC27s!
return if $pcno == 27;
# spots
if ($field[3] > 0) {
- my @in = reverse Spot::search(1, undef, undef, 0, $field[3]-1);
+ my @in = reverse Spot::search(1, undef, undef, 0, $field[3]);
my $in;
foreach $in (@in) {
$self->send(pc26(@{$in}[0..4], $field[2]));
}
if (($pcno >= 28 && $pcno <= 33) || $pcno == 40 || $pcno == 42 || $pcno == 49) { # mail/file handling
- if ($field[1] eq $main::mycall) {
+ if ($pcno == 49 || $field[1] eq $main::mycall) {
DXMsg::process($self, $line);
} else {
route($field[1], $line);
if ($pcno == 43) {
last SWITCH;
}
- if ($pcno == 37 || $pcno == 44 || $pcno == 45 || $pcno == 46 || $pcno == 47 || $pcno == 49) {
+ if ($pcno == 37 || $pcno == 44 || $pcno == 45 || $pcno == 46 || $pcno == 47) {
if ($field[1] eq $main::mycall) {
;
} else {
# unbusy and stop and outgoing mail
my $mref = DXMsg::get_busy($call);
- $mref->stop_msg($self) if $mref;
+ $mref->stop_msg($call) if $mref;
# broadcast to all other nodes that all the nodes connected to via me are gone
my @gonenodes = map { $_->dxchan == $self ? $_ : () } DXNode::get_all();
# taking into account filtering and so on
foreach $dxchan (@dxchan) {
my $routeit;
- my ($filter, $hops) = Filter::it($dxchan->{spotfilter}, @_, $self->{call} ) if $dxchan->{spotfilter};
+ my ($filter, $hops);
+
+ if ($dxchan->{spotfilter}) {
+ ($filter, $hops) = Filter::it($dxchan->{spotfilter}, @_, $self->{call} );
+ next unless $filter;
+ }
+
if ($dxchan->is_ak1a) {
next if $dxchan == $self;
if ($hops) {