+12Mar25======================================================================
+1. Add some spot rate limiting.
+2. Remove some obsolete spot deduping options that have not effectively been
+ changed in several years and simplify the code to just use my preferred
+ options.
19Feb25======================================================================
1. Make sure that the routing table has a number of users as well as a last
PC92 C records. This will prevent some of the false negatives (just not
# Store it here (but only if it isn't baddx)
my $t = (int ($main::systime/60)) * 60;
-return (1, $self->msg('dup')) if Spot::dup_find($freq, $spotted, $t, $line, $spotter, $main::mycall);
+#return (1, $self->msg('dup')) if Spot::dup_find($freq, $spotted, $t, $line, $spotter, $main::mycall);
my @spot = Spot::prepare($freq, $spotted, $t, $line, $spotter, $main::mycall, $ipaddr);
#$DB::single = 1;
} else {
# store in spots database
unless (Spot::dup_find(@spot)) {
- Spot::dup_add(0, @spot);
- Spot::add(@spot);
- $self->dx_spot(undef, undef, @spot);
+ Spot::add_local(@spot);
DXProt::send_dx_spot($self, $spot, @spot);
} else {
- push @out, "Duplicate spot: $line";
+# push @out, "Duplicate spot: $line";
LogDbg("DXCommand", "Spot dupe from $spotter: $line");
- }
+ }
+ # put this here so that the spotter does not know that it is a dupe or not
+ $self->dx_spot(undef, undef, @spot);
}
}
for my $ip (@_) {
# protect against stupid or malicious
next unless is_ipaddr($ip);
- next if $ip =~ /^127\./;
- next if $ip =~ /^::1$/;
+# next if $ip =~ /^127\./;
+# next if $ip =~ /^::1$/;
# next if find($ip);
if ($ip =~ /\./) {
eval {$ipv4->add_any($ip)};
{
return () unless $active;
my @out;
- push @out, $ipv4->list if $count4;
- push @out, $ipv6->list if $count6;
+ push @out, $ipv4->list, $ipv4->list_range if $count4;
+ push @out, $ipv6->list, $ipv6->list_range if $count6;
return _sort(@out);
}
foreach my $ref (@{$dxchan->{sluggedpcs}}) {
if ($ref->[0] == 61) {
unless (Spot::dup_find(@{$ref->[2]})) {
- Spot::dup_add(@{$ref->[2]});
+ Spot::dup_new(@{$ref->[2]});
DXProt::send_dx_spot($dxchan, $ref->[1], @{$ref->[2]});
} else {
dbg("DXCommand: process slugged spot $ref->[1] is a dupe, ignored" );
return unless $s;
$d{$s} = $t;
- dbg("DXDupe::add key: $s time: " . ztime($t)) if isdbg('dxdupe');
+ dbg("DXDupe::add key: $s time: " . htime($t)) if isdbg('dxdupe');
}
sub del
return unless $s;
my $t = $d{$s};
- dbg("DXDupe::del key: $s time: " . ztime($t)) if isdbg('dxdupe');
+ dbg("DXDupe::del key: $s time: " . htime($t)) if isdbg('dxdupe');
delete $d{$s};
}
-sub per_minute
+sub clean
{
my @del;
my $count = 0;
}
++$count;
if (isdbg("dxdupeclean")) {
- dbg("DXDupe::per_minute key:$flag$left") if isdbg('dxdupeclean');
+ dbg("DXDupe::clean key:$flag$left") if isdbg('dxdupeclean');
}
}
for (@del) {
del($_);
}
- dbg("DXDupe::per_minute number of records " . scalar keys %d) if isdbg('dxdupe');
+ dbg("DXDupe::clean number of records " . scalar keys %d) if isdbg('dxdupe');
$lasttime = $main::systime;
}
sub sendinit
{
my $self = shift;
- $self->send(pc18(($self->{isolate} || !$self->user->wantpc9x) ? "" : " pc9x"));
+ $self->send(pc18(($self->{isolate} || !$self->user->wantpc9x) ? "" : " pc9x 91"));
}
#
#
#
- if (Spot::dup_add(0, @spot[0..4,7])) {
+ if (Spot::dup_find(@spot[0..4,7])) {
dbg("PCPROT: Duplicate Spot $self->{call}: $pc->[0] $key ignored\n") if isdbg('chanerr') || isdbg('dupespot') || isdbg('pc11');
return;
}
}
#
- # Now finally: save the spot itself and send it on its merry way to the users
+ # Now finally: save the spot itself and then send it on its merry way to the users
#
-
- Spot::add(@spot);
+
+ Spot::add_local(@spot);
my $ip = '';
$ip ||= $spot[14] if exists $spot[14];
} elsif (!$self->user->wantpc9x) {
dbg("PC18 $self->{call} pc9x explicitly switched off, using old protocol");
} else {
+ $self->{pc91} = $pc->[1] =~ /\b91/;
$self->{do_pc9x} = 1;
- dbg("PC18 $self->{call} Set do PC9x");
+ dbg("PC18 $self->{call} Set do " . $self->{pc91} ? "PC9[123]" : "PC9[23]");
}
}
is_qra is_freq is_digits is_pctext is_pcflag insertitem deleteitem
is_prefix dd is_ipaddr $pi $d2r $r2d localdata localdata_mv
diffms _diffms _diffus difft parraydifft is_ztime basecall
- normalise_call is_numeric
+ normalise_call is_numeric htime
);
return $buf;
}
+sub htime
+{
+ my $t = shift;
+ $t = defined $t ? $t : time;
+ my $dst = shift;
+ my ($sec,$min,$hour) = $dst ? localtime($t): gmtime($t);
+ my $buf = sprintf "%02d:%02d:%02d%s", $hour, $min, $sec, ($dst) ? '' : 'Z';
+ return $buf;
+}
+
# get a zulu time in cluster format (2300Z)
sub ztime
{
$t = $adds - $b;
$adds = shift;
} else {
- $t = $main::systime - $b;
+ $t = time - $b;
}
}
return '-(ve)' if $t < 0;
our $readback = $main::is_win ? 0 : 1; # don't read spot files backwards if it's windows
our $qrggranularity = 1; # normalise the qrg to this number of khz (default: 25khz), so tough luck if you have a fumble fingers moment
our $timegranularity = 600; # ditto to the nearest 100 seconds
-our $oldstyle = 0; # revert to traditional dupe key format
-our $no_node_in_dupe = 1; # remove the node field from dupe considerations.
+our $dupebycall = 11*60+5; # check that call is not spotted by the same callsign too often - this the interval that each (base) call by pair can recur
+our $store_otext = 0; # also store the original rather than "normalised" text/info field - now obsolescent
+
if ($readback) {
$readback = `which tac`;
return @out;
}
-sub add
+sub add_local
{
my $buf = join('^', @_);
+
+ dup_new(@_);
+
$fp->writeunix($_[2], $buf);
if ($spotcachedays > 0) {
my $now = Julian::Day->new($_[2]);
last if $count >= $to; # stop after to
}
}
- }
+7 }
return ("Spot search error", $@) if $@;
@out = sort {$b->[2] <=> $a->[2]} @out if @out;
{
my ($just_find, $freq, $call, $d, $text, $by, $node) = @_;
- dbg("Spot::dup: freq=$freq call=$call d=$d text='$text' by=$by node=$node" . ($just_find ? " jf=$just_find" : "")) if isdbg('spotdup');
+ dbg("Spot::add_dup: freq=$freq call=$call d=$d text='$text' by=$by node=$node" . ($just_find ? " JF" : "")) if isdbg('spotdup');
# dump if too old
return 2 if $d < $main::systime - $dupage;
my $nd = nearest($timegranularity, $d);
- # remove SSID or area
- $by =~ s|[-/]\d+$||;
-
+
$freq = sprintf "%.1f", $freq; # normalise frequency
# $freq = int $freq; # normalise frequency
$call = substr($call, 0, $maxcalllth) if length $call > $maxcalllth;
- my $dtext ;
+ # remove SSID or area on call, by and node
+ $call = basecall($call);
+ $by = basecall($by);
+ $node = basecall($node);
+
+ my $t = 0;
+ my $ldupkey;
+ my $dtext;
my $l = length $text;
$dtext = qq{original:'$text'($l)} if isdbg('spottext');
$text =~ s/\%([0-9A-F][0-9A-F])/chr(hex($1))/eg;
$text = uc unpad($text);
+ $text =~ s/^\s*\d{1,2}[-+.:]\d\d\s+//; # remove anything that looks like a time from the front
$l = length $text;
$dtext .= qq{->afterhex: '$text'($l)} if isdbg('spottext');
$l = length $text;
$dtext .= qq{->final:'$text'($l)} if isdbg('spottext');
- my $t = 0;
- my $ldupkey;
-
- # new feature: don't include the origin node in Spot dupes
- # default = true
- $node = '' if $no_node_in_dupe;
- $ldupkey = $oldstyle ? "X$call|$by|$freq|$nd|$node|$text" : "X$call|$by|$qrg|$nd|$node|$text";
-
+ # new feature: don't include the origin node in Spot dupes and use normalised qrg, rather than raw freq
+ # $text = normalised text
+ $ldupkey = "X$call|$by|$qrg|$text";
$t = DXDupe::find($ldupkey);
- dbg("Spot::dup ldupkey $ldupkey t '$t'" . ($t?' DUPE':' NEW')) if isdbg('spotdup');
+ dbg("Spot::add_dup ldupkey $ldupkey" . ($t?(' DUPE=>'.htime($t)) :' NEW')) if isdbg('spotdup');
$dtext .= ' DUPE' if $t;
dbg("text transforms: $dtext") if length $text && isdbg('spottext');
- return 1 if $t > 0;
-
+
+ # re-add it to kick the timer down the road. REMEMBER: dupes are in a tied hash so
+ # this is effectively an update
+ if ($t > 0) {
+# DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+ return 1;
+ }
DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+
+ # $otext = slightly edited original text
+ if ($store_otext) {
+ $otext = substr($otext, 0, $duplth) if length $otext > $duplth;
+ $otext =~ s/\s+$//;
+ if (length $otext && $otext ne $text) {
+ $ldupkey = "X$call|$by|$qrg|$otext";
+ $t = DXDupe::find($ldupkey);
+ dbg("Spot::add_dup (OTEXT) ldupkey $ldupkey". ($t?(' (DUPE=>'.htime($t)) :' NEW')) if isdbg('spotdup');
+ if (isdbg('spottext')) {
+ $dtext .= sprintf q{ DUBIOUS '%s'}, join '', @dubious if @dubious;
+ $dtext .= ' DUPE (OTEXT)' if $t;
+ dbg("text transforms: $dtext") if length $text;
+ }
+ # see above
+ if ($t > 0) {
+# DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+ return 1;
+ }
+ DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+ }
+ }
- $otext = substr($otext, 0, $duplth) if length $otext > $duplth;
- $otext =~ s/\s+$//;
- if (length $otext && $otext ne $text) {
- $ldupkey = $oldstyle ? "X$call|$by|$freq|$otext" : "X$call|$by|$qrg|$nd|$otext";
+ if ($dupebycall) {
+ $ldupkey = "X$by|$call";
$t = DXDupe::find($ldupkey);
- dbg("Spot::dup (OTEXT) ldupkey $ldupkey t '$t'" . ($t?' DUPE':' NEW')) if isdbg('spotdup');
- if (isdbg('spottext')) {
- $dtext .= sprintf q{ DUBIOUS '%s'}, join '', @dubious if @dubious;
- $dtext .= ' DUPE (OTEXT)' if $t;
- dbg("text transforms: $dtext") if length $text;
+ dbg("Spot::add_dup by call $ldupkey" . ($t?(' DUPE=>'.htime($t)) :' NEW')) if isdbg('spotdup');
+ # see above
+ if ($t > 0) {
+# DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+ return 1;
}
- return 1 if $t > 0;
- DXDupe::add($ldupkey, $main::systime+$dupage) unless $just_find;
+
+ DXDupe::add($ldupkey, $main::systime+$dupebycall) unless $just_find;
}
+
return undef;
}
return dup_add(1, @_);
}
+sub dup_new
+{
+ return dup_add(0, @_);
+}
+
sub listdups
{
return DXDupe::listdups('X', $dupage, @_);
sub per_10_sec
{
-
+ DXDupe::clean();
}
sub per_minute
{
RBN::per_minute();
- DXDupe::per_minute();
}
sub per_10_minute