X-Git-Url: http://gb7djk.dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXProt.pm;h=5f910bbbc4cc6ffd99ef40426f447797ce6b49b8;hb=e8df1ab836f28cc7a703c524af0410070d4258cb;hp=ec18e19f499f4298921d127909f01ab6644c14fe;hpb=eb944656dcd2b715338ea025fbad11e918506e26;p=spider.git diff --git a/perl/DXProt.pm b/perl/DXProt.pm index ec18e19f..5f910bbb 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -38,12 +38,13 @@ use strict; use vars qw($VERSION $BRANCH); $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ ); -$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ ) || 0; +$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0)); $main::build += $VERSION; $main::branch += $BRANCH; -use vars qw($pc11_max_age $pc23_max_age $last_pc50 +use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restime $eph_pc34_restime $last_hour $last10 %eph %pings %rcmds $ann_to_talk + $pingint $obscount %pc19list %nodehops $baddx $badspotter $badnode $censorpc $rspfcheck $allowzero $decode_dk0wcy $send_opernam @checklist); @@ -54,6 +55,8 @@ $last_hour = time; # last time I did an hourly periodic update %pings = (); # outstanding ping requests outbound %rcmds = (); # outstanding rcmd requests outbound %nodehops = (); # node specific hop control +%pc19list = (); # list of outstanding PC19s that haven't had PC16s on them + $censorpc = 1; # Do a BadWords::check on text fields and reject things # loads of 'bad things' $baddx = new DXHash "baddx"; @@ -62,6 +65,11 @@ $badnode = new DXHash "badnode"; $last10 = $last_pc50 = time; $ann_to_talk = 1; $rspfcheck = 1; +$eph_restime = 180; +$eph_info_restime = 60*60; +$eph_pc34_restime = 30; +$pingint = 5*60; +$obscount = 2; @checklist = ( @@ -182,19 +190,8 @@ sub check sub init { - my $user = DXUser->get($main::mycall); - $DXProt::myprot_version += $main::version*100; - $main::me = DXProt->new($main::mycall, 0, $user); - $main::me->{here} = 1; - $main::me->{state} = "indifferent"; do "$main::data/hop_table.pl" if -e "$main::data/hop_table.pl"; confess $@ if $@; - $main::me->{sort} = 'S'; # S for spider - $main::me->{priv} = 9; - $main::me->{metric} = 0; - $main::me->{pingave} = 0; - -# $Route::Node::me->adddxchan($main::me); } # @@ -263,9 +260,9 @@ sub start # ping neighbour node stuff my $ping = $user->pingint; - $ping = 5*60 unless defined $ping; + $ping = $pingint unless defined $ping; $self->{pingint} = $ping; - $self->{nopings} = $user->nopings || 2; + $self->{nopings} = $user->nopings || $obscount; $self->{pingtime} = [ ]; $self->{pingave} = 999; $self->{metric} ||= 100; @@ -273,7 +270,7 @@ sub start # send initialisation string unless ($self->{outbound}) { - $self->send(pc18()); + $self->sendinit; } $self->state('init'); @@ -287,6 +284,16 @@ sub start $script->run($self) if $script; } +# +# send outgoing 'challenge' +# + +sub sendinit +{ + my $self = shift; + $self->send(pc18()); +} + # # This is the normal pcxx despatcher # @@ -346,6 +353,20 @@ sub normal $to = $field[2]; } + # if this is a 'nodx' node then ignore it + if ($badnode->in($field[6]) || ($via && $badnode->in($via))) { + dbg("PCPROT: Bad Node, dropped") if isdbg('chanerr'); + return; + } + + # if this is a 'bad spotter' user then ignore it + my $nossid = $from; + $nossid =~ s/-\d+$//; + if ($badspotter->in($nossid)) { + dbg("PCPROT: Bad Spotter, dropped") if isdbg('chanerr'); + return; + } + # if we are converting announces to talk is it a dup? if ($ann_to_talk) { if (AnnTalk::is_talk_candidate($from, $field[3]) && AnnTalk::dup($from, $to, $field[3])) { @@ -405,7 +426,9 @@ sub normal } # if this is a 'bad spotter' user then ignore it - if ($badspotter->in($field[6])) { + my $nossid = $field[6]; + $nossid =~ s/-\d+$//; + if ($badspotter->in($nossid)) { dbg("PCPROT: Bad Spotter, dropped") if isdbg('chanerr'); return; } @@ -439,6 +462,7 @@ sub normal } } + my @spot = Spot::prepare($field[1], $field[2], $d, $field[5], $field[6], $field[7]); # global spot filtering on INPUT if ($self->{inspotsfilter}) { @@ -448,8 +472,11 @@ sub normal return; } } - - if (Spot::dup($field[1], $field[2], $d, $field[5])) { + + # this goes after the input filtering, but before the add + # so that if it is input filtered, it isn't added to the dup + # list. This allows it to come in from a "legitimate" source + if (Spot::dup($field[1], $field[2], $d, $field[5], $field[6])) { dbg("PCPROT: Duplicate Spot ignored\n") if isdbg('chanerr'); return; } @@ -542,6 +569,20 @@ sub normal } } + # if this is a 'nodx' node then ignore it + if ($badnode->in($field[5])) { + dbg("PCPROT: Bad Node, dropped") if isdbg('chanerr'); + return; + } + + # if this is a 'bad spotter' user then ignore it + my $nossid = $field[1]; + $nossid =~ s/-\d+$//; + if ($badspotter->in($nossid)) { + dbg("PCPROT: Bad Spotter, dropped") if isdbg('chanerr'); + return; + } + if ($field[2] eq '*' || $field[2] eq $main::mycall) { @@ -589,24 +630,82 @@ sub normal my $ncall = $field[1]; my $newline = "PC16^"; + # do I want users from this channel? + unless ($self->user->wantpc16) { + dbg("PCPROT: don't send users to $self->{call}") if isdbg('chanerr'); + return; + } + # is it me? if ($ncall eq $main::mycall) { dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); return; } my $parent = Route::Node::get($ncall); + + # if there is a parent, proceed, otherwise if there is a latent PC19 in the PC19list, + # fix it up in the routing tables and issue it forth before the PC16 unless ($parent) { - dbg("PCPROT: Node $ncall not in config") if isdbg('chanerr'); - return; - } - $dxchan = $parent->dxchan; - if ($dxchan && $dxchan ne $self) { - dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); - return; + my $nl = $pc19list{$ncall}; + + if ($nl && @field > 3) { # 3 because of the hop count! + + # this is a new (remembered) node, now attach it to me if it isn't in filtered + # and we haven't disallowed it + my $user = DXUser->get_current($ncall); + if (!$user) { + $user = DXUser->new($ncall); + $user->sort('A'); + $user->priv(1); # I have relented and defaulted nodes + $user->lockout(1); + $user->homenode($ncall); + $user->node($ncall); + } + + my $wantpc19 = $user->wantroutepc19; + if ($wantpc19 || !defined $wantpc19) { + my $new = Route->new($ncall); # throw away + if ($self->in_filter_route($new)) { + my @nrout; + for (@$nl) { + $parent = Route::Node::get($_->[0]); + $dxchan = $parent->dxchan if $parent; + if ($dxchan && $dxchan ne $self) { + dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); + $parent = undef; + } + if ($parent) { + my $r = $parent->add($ncall, $_->[1], $_->[2]); + push @nrout, $r unless @nrout; + } + } + $user->wantroutepc19(1) unless defined $wantpc19; # for now we work on the basis that pc16 = real route + $user->lastin($main::systime) unless DXChannel->get($ncall); + $user->put; + + # route the pc19 - this will cause 'stuttering PC19s' for a while + $self->route_pc19(@nrout) if @nrout ; + $parent = Route::Node::get($ncall); + } else { + return; + } + delete $pc19list{$ncall}; + } + } else { + dbg("PCPROT: Node $ncall not in config") if isdbg('chanerr'); + return; + } + } else { + + $dxchan = $parent->dxchan; + if ($dxchan && $dxchan ne $self) { + dbg("PCPROT: PC16 from $self->{call} trying to alter locally connected $ncall, ignored!") if isdbg('chanerr'); + return; + } + + # input filter if required + return unless $self->in_filter_route($parent); } - # input filter if required - return unless $self->in_filter_route($parent); - my $i; my @rout; for ($i = 2; $i < $#field; $i++) { @@ -614,7 +713,7 @@ sub normal next unless $call && $conf && defined $here && is_callsign($call); next if $call eq $main::mycall; - eph_del_regex("^PC17\^$call\^$ncall"); + eph_del_regex("^PC17\\^$call\\^$ncall"); $conf = $conf eq '*'; @@ -638,6 +737,7 @@ sub normal } else { push @rout, $parent->add_user($call, $flags); } + # add this station to the user database, if required $call =~ s/-\d+$//o; # remove ssid for users @@ -661,13 +761,13 @@ sub normal my $ncall = $field[2]; my $ucall = $field[1]; - if (eph_dup($line)) { - dbg("PCPROT: dup PC17 detected") if isdbg('chanerr'); + eph_del_regex("^PC16\\^$ncall.*$ucall"); + + # do I want users from this channel? + unless ($self->user->wantpc16) { + dbg("PCPROT: don't send users to $self->{call}") if isdbg('chanerr'); return; } - - eph_del_regex("^PC16.*$ncall.*$ucall"); - if ($ncall eq $main::mycall) { dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); return; @@ -693,15 +793,37 @@ sub normal # input filter if required return unless $self->in_filter_route($parent); - my @rout = $parent->del_user($uref); + $parent->del_user($uref); + + if (eph_dup($line)) { + dbg("PCPROT: dup PC17 detected") if isdbg('chanerr'); + return; + } - $self->route_pc17($parent, @rout) if @rout; + $self->route_pc17($parent, $uref); return; } if ($pcno == 18) { # link request $self->state('init'); + # record the type and version offered + if ($field[1] =~ /DXSpider Version: (\d+\.\d+) Build: (\d+\.\d+)/) { + $self->version(53 + $1); + $self->user->version(53 + $1); + $self->build(0 + $2); + $self->user->build(0 + $2); + unless ($self->is_spider) { + $self->user->sort('S'); + $self->user->put; + $self->sort('S'); + } + } else { + $self->version(50.0); + $self->version($field[2] / 100) if $field[2] && $field[2] =~ /^\d+$/; + $self->user->version($self->version); + } + # first clear out any nodes on this dxchannel my $parent = Route::Node::get($self->{call}); my @rout = $parent->del_nodes; @@ -737,7 +859,7 @@ sub normal my $ver = $field[$i+3]; next unless defined $here && defined $conf && is_callsign($call); - eph_del_regex("^PC(?:21\^$call|17\^[^\^]+\^$call)"); + eph_del_regex("^PC(?:21\\^$call|17\\^[^\\^]+\\^$call)"); # check for sane parameters # $ver = 5000 if $ver eq '0000'; @@ -749,12 +871,24 @@ sub normal my $dxchan = DXChannel->get($call); if ($dxchan && $dxchan != $self) { dbg("PCPROT: PC19 from $self->{call} trying to alter wrong locally connected $call, ignored!") if isdbg('chanerr'); - return; + next; + } + + # add this station to the user database, if required (don't remove SSID from nodes) + my $user = DXUser->get_current($call); + if (!$user) { + $user = DXUser->new($call); + $user->sort('A'); + $user->priv(1); # I have relented and defaulted nodes + $user->lockout(1); + $user->homenode($call); + $user->node($call); } - # update it if required my $r = Route::Node::get($call); my $flags = Route::here($here)|Route::conf($conf); + + # modify the routing table if it is in it, otherwise store it in the pc19list for now if ($r) { my $ar; if ($call ne $parent->call) { @@ -771,17 +905,20 @@ sub normal push @rout, $r unless $ar; } } else { - if ($call eq $self->{call}) { - dbg("DXPROT: my channel route for $call has disappeared"); - next; - }; - - my $new = Route->new($call); # throw away - if ($self->in_filter_route($new)) { - my $r = $parent->add($call, $ver, $flags); - push @rout, $r; + + # if he is directly connected or allowed then add him, otherwise store him up for later + if ($call eq $self->{call} || $user->wantroutepc19) { + my $new = Route->new($call); # throw away + if ($self->in_filter_route($new)) { + my $ar = $parent->add($call, $ver, $flags); + push @rout, $ar if $ar; + } else { + next; + } } else { - next; + $pc19list{$call} = [] unless exists $pc19list{$call}; + my $nl = $pc19list{$call}; + push @{$pc19list{$call}}, [$self->{call}, $ver, $flags] unless grep $_->[0] eq $self->{call}, @$nl; } } @@ -789,16 +926,6 @@ sub normal my $mref = DXMsg::get_busy($call); $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); - if (!$user) { - $user = DXUser->new($call); - $user->sort('A'); - $user->priv(1); # I have relented and defaulted nodes - $user->lockout(1); - $user->homenode($call); - $user->node($call); - } $user->lastin($main::systime) unless DXChannel->get($call); $user->put; } @@ -819,44 +946,49 @@ sub normal if ($pcno == 21) { # delete a cluster from the list my $call = uc $field[1]; - if (eph_dup($line)) { - dbg("PCPROT: dup PC21 detected") if isdbg('chanerr'); + eph_del_regex("^PC1[679].*$call"); + + # if I get a PC21 from the same callsign as self then treat it + # as a PC39: I have gone away + if ($call eq $self->call) { + $self->disconnect(1); return; } - eph_del_regex("^PC1[79].*$call"); - + # check to see if we are in the pc19list, if we are then don't bother with any of + # this routing table manipulation, just remove it from the list and dump it my @rout; - my $parent = Route::Node::get($self->{call}); - unless ($parent) { - dbg("DXPROT: my parent $self->{call} has disappeared"); - $self->disconnect; - return; - } - if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me! - if ($call eq $self->{call}) { - dbg("PCPROT: Trying to disconnect myself with PC21") if isdbg('chanerr'); + if (my $nl = $pc19list{$call}) { + $pc19list{$call} = [ grep {$_->[0] ne $self->{call}} @$nl ]; + delete $pc19list{$call} unless @{$pc19list{$call}}; + } else { + + my $parent = Route::Node::get($self->{call}); + unless ($parent) { + dbg("DXPROT: my parent $self->{call} has disappeared"); + $self->disconnect; return; } - - my $node = Route::Node::get($call); - if ($node) { - - my $dxchan = DXChannel->get($call); - if ($dxchan && $dxchan != $self) { - dbg("PCPROT: PC21 from $self->{call} trying to alter locally connected $call, ignored!") if isdbg('chanerr'); - return; + if ($call ne $main::mycall) { # don't allow malicious buggers to disconnect me! + my $node = Route::Node::get($call); + if ($node) { + + my $dxchan = DXChannel->get($call); + if ($dxchan && $dxchan != $self) { + dbg("PCPROT: PC21 from $self->{call} trying to alter locally connected $call, ignored!") if isdbg('chanerr'); + return; + } + + # input filter it + return unless $self->in_filter_route($node); + + # routing objects + push @rout, $node->del($parent); } - - # input filter it - return unless $self->in_filter_route($node); - - # routing objects - push @rout, $node->del($parent); + } else { + dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr'); + return; } - } else { - dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr'); - return; } $self->route_pc21(@rout) if @rout; @@ -975,11 +1107,16 @@ sub normal } if ($pcno == 34 || $pcno == 36) { # remote commands (incoming) - $self->process_rcmd($field[1], $field[2], $field[2], $field[3]); + if (eph_dup($line, $eph_pc34_restime)) { + dbg("PCPROT: dupe") if isdbg('chanerr'); + } else { + $self->process_rcmd($field[1], $field[2], $field[2], $field[3]); + } return; } if ($pcno == 35) { # remote command replies + eph_del_regex("^PC35\\^$field[2]\\^$field[1]\\^"); $self->process_rcmd_reply($field[1], $field[2], $field[1], $field[3]); return; } @@ -993,7 +1130,6 @@ sub normal if ($pcno == 39) { # incoming disconnect if ($field[1] eq $self->{call}) { $self->disconnect(1); - eph_del_regex("^PC(?:1[679]|21).*$field[1]"); } else { dbg("PCPROT: came in on wrong channel") if isdbg('chanerr'); } @@ -1003,6 +1139,11 @@ sub normal if ($pcno == 41) { # user info my $call = $field[1]; + if (eph_dup($line, $eph_info_restime)) { + dbg("PCPROT: dupe") if isdbg('chanerr'); + return; + } + # input filter if required # my $ref = Route::get($call) || Route->new($call); # return unless $self->in_filter_route($ref); @@ -1014,7 +1155,7 @@ sub normal # add this station to the user database, if required my $user = DXUser->get_current($call); - $user = DXUser->new($call) if !$user; + $user = DXUser->new($call) unless $user; if ($field[2] == 1) { $user->name($field[3]); @@ -1033,11 +1174,11 @@ sub normal } elsif ($field[2] == 4) { $user->homenode($field[3]); } elsif ($field[2] == 5) { - if (is_qra($field[3])) { - my ($lat, $long) = DXBearing::qratoll($field[3]); + if (is_qra(uc $field[3])) { + my ($lat, $long) = DXBearing::qratoll(uc $field[3]); $user->lat($lat); $user->long($long); - $user->qra($field[3]); + $user->qra(uc $field[3]); } else { dbg('PCPROT: not a valid QRA locator') if isdbg('chanerr'); return; @@ -1046,9 +1187,13 @@ sub normal $user->lastoper($main::systime); # to cut down on excessive for/opers being generated $user->put; + unless ($self->{isolate}) { + DXChannel::broadcast_nodes($line, $self); # send it to everyone but me + } + # perhaps this IS what we want after all # $self->route_pc41($ref, $call, $field[2], $field[3], $field[4]); -# return; + return; } if ($pcno == 43) { @@ -1116,11 +1261,6 @@ sub normal } else { $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6); } -# my $st; -# for (@{$tochan->{pingtime}}) { -# $st += $_; -# } -# $tochan->{pingave} = $st / @{$tochan->{pingtime}}; $tochan->{nopings} = $nopings; # pump up the timer } } @@ -1156,7 +1296,7 @@ sub normal return; } @field = map { unpad($_) } @field; - if (WCY::dup($d,@field[3..7])) { + if (WCY::dup($d)) { dbg("PCPROT: Dup WCY Spot ignored\n") if isdbg('chanerr'); return; } @@ -1165,7 +1305,7 @@ sub normal my $rep; eval { - $rep = Local::wwv($self, @field[1..12]); + $rep = Local::wcy($self, @field[1..12]); }; # dbg("Local::wcy error $@") if isdbg('local') if $@; return if $rep; @@ -1185,6 +1325,9 @@ sub normal return; } + if ($pcno == 90) { # new style PC16,17,19,21 + return; + } } # if get here then rebroadcast the thing with its Hop count decremented (if @@ -1226,7 +1369,7 @@ sub process next unless $dxchan->is_node(); next if $dxchan == $main::me; - # send the pc50 + # send the pc50 or PC90 $dxchan->send($pc50s) if $pc50s; # send a ping out on this channel @@ -1263,6 +1406,7 @@ sub process # some active measures # + sub send_dx_spot { my $self = shift; @@ -1431,24 +1575,27 @@ sub send_announce # obtain country codes etc my ($ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq) = (0..0); + my ($ann_state, $org_state) = ("", ""); my @dxcc = Prefix::extract($_[0]); if (@dxcc > 0) { $ann_dxcc = $dxcc[1]->dxcc; $ann_itu = $dxcc[1]->itu; $ann_cq = $dxcc[1]->cq; + $ann_state = $dxcc[1]->state; } @dxcc = Prefix::extract($_[4]); if (@dxcc > 0) { $org_dxcc = $dxcc[1]->dxcc; $org_itu = $dxcc[1]->itu; $org_cq = $dxcc[1]->cq; + $org_state = $dxcc[1]->state; } if ($self->{inannfilter}) { my ($filter, $hops) = $self->{inannfilter}->it(@_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, - $org_dxcc, $org_itu, $org_cq); + $org_dxcc, $org_itu, $org_cq, $ann_state, $org_state); unless ($filter) { dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr'); return; @@ -1492,7 +1639,7 @@ sub announce sub send_local_config { my $self = shift; - my $n; + my $node; my @nodes; my @localnodes; my @remotenodes; @@ -1511,18 +1658,20 @@ sub send_local_config my @intcalls = map { $_->nodes } @localnodes if @localnodes; my $ref = Route::Node::get($self->{call}); my @rnodes = $ref->nodes; - for my $n (@intcalls) { - push @remotenodes, Route::Node::get($n) unless grep $n eq $_, @rnodes; + for my $node (@intcalls) { + push @remotenodes, Route::Node::get($node) unless grep $node eq $_, @rnodes; } unshift @localnodes, $main::routeroot; } - send_route($self, \&pc19, scalar(@localnodes)+scalar(@remotenodes), @localnodes, @remotenodes); + + $self->send_route(\&pc19, scalar(@localnodes)+scalar(@remotenodes), @localnodes, @remotenodes); # get all the users connected on the above nodes and send them out - foreach $n (@localnodes, @remotenodes) { - if ($n) { - send_route($self, \&pc16, 1, $n, map {my $r = Route::User::get($_); $r ? ($r) : ()} $n->users); + foreach $node (@localnodes, @remotenodes) { + if ($node) { + my @rout = map {my $r = Route::User::get($_); $r ? ($r) : ()} $node->users; + $self->send_route(\&pc16, 1, $node, @rout) if @rout && $self->user->wantsendpc16; } else { dbg("sent a null value") if isdbg('chanerr'); } @@ -1619,7 +1768,7 @@ sub load_hops return $self->msg('lh1') unless -e "$main::data/hop_table.pl"; do "$main::data/hop_table.pl"; return $@ if $@; - return 0; + return (); } @@ -1743,13 +1892,35 @@ sub disconnect $self->send_now("D", DXProt::pc39($main::mycall, $self->msg('disc1', "System Op"))); } - # do routing stuff + # get rid of any PC16/17/19/21s + eph_del_regex("^PC(?:1[679]|21).*$call"); + + # do routing stuff, remove me from routing table my $node = Route::Node::get($call); my @rout; if ($node) { @rout = $node->del($main::routeroot); + + # and all my ephemera as well + for (@rout) { + my $c = $_->call; + eph_del_regex("^PC(?:1[679]|21).*$c"); + } } + # remove them from the pc19list as well + while (my ($k,$v) = each %pc19list) { + my @l = grep {$_->[0] ne $call} @{$pc19list{$k}}; + if (@l) { + $pc19list{$k} = \@l; + } else { + delete $pc19list{$k}; + } + + # and the ephemera + eph_del_regex("^PC(?:1[679]|21).*$k"); + } + # unbusy and stop and outgoing mail my $mref = DXMsg::get_busy($call); $mref->stop_msg($call) if $mref; @@ -1803,7 +1974,7 @@ sub send_route if (!$self->{isolate} && $self->{routefilter}) { $filter = undef; if ($r) { - ($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq); + ($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq, $self->{state}, $r->{state}); if ($filter) { push @rin, $r; } else { @@ -1842,6 +2013,9 @@ sub broadcast_route foreach $dxchan (@dxchan) { next if $dxchan == $self; next if $dxchan == $main::me; + next if $dxchan->user->wantnp; + next if ($generate == \&pc16 || $generate==\&pc17) && !$dxchan->user->wantsendpc16; + $dxchan->send_route($generate, @_); } } @@ -1850,12 +2024,14 @@ sub broadcast_route sub route_pc16 { my $self = shift; + return unless $self->user->wantpc16; broadcast_route($self, \&pc16, 1, @_); } sub route_pc17 { my $self = shift; + return unless $self->user->wantpc16; broadcast_route($self, \&pc17, 1, @_); } @@ -1889,6 +2065,12 @@ sub route_pc50 broadcast_route($self, \&pc50, 1, @_); } +sub route_pc90 +{ + my $self = shift; + broadcast_route($self, \&pc90, 1, @_); +} + sub in_filter_route { my $self = shift; @@ -1896,7 +2078,7 @@ sub in_filter_route my ($filter, $hops) = (1, 1); if ($self->{inroutefilter}) { - ($filter, $hops) = $self->{inroutefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq); + ($filter, $hops) = $self->{inroutefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq, $self->state, $r->state); dbg("PCPROT: $self->{call}/" . $r->call . ' rejected by in_filter_route') if !$filter && isdbg('chanerr'); } return $filter; @@ -1905,12 +2087,13 @@ sub in_filter_route sub eph_dup { my $s = shift; + my $t = shift || $eph_restime; my $r; # chop the end off $s =~ s/\^H\d\d?\^?\~?$//; $r = 1 if exists $eph{$s}; # pump up the dup if it keeps circulating - $eph{$s} = $main::systime; + $eph{$s} = $main::systime + $t; return $r; } @@ -1930,11 +2113,26 @@ sub eph_clean my ($key, $val); while (($key, $val) = each %eph) { - if ($main::systime - $val > 180) { + if ($main::systime >= $val) { delete $eph{$key}; } } } +sub eph_list +{ + my ($key, $val); + my @out; + + while (($key, $val) = each %eph) { + push @out, $key, $val; + } + return @out; +} + +sub run_cmd +{ + goto &DXCommandmode::run_cmd; +} 1; __END__