From 2c50f9b4b2b3f29b000d77623a9d7c3748933aef Mon Sep 17 00:00:00 2001 From: Dirk Koopman Date: Mon, 17 Sep 2007 22:44:15 +0100 Subject: [PATCH] new keepalive system + timings for PC92 C recs Added the new K record for keepalives. Increased the PC92 C interval to 24 hours. Increased dependent node C interval to 2 hours. PC50 can reset obs. PC50 now routed everywhere without filters except isolation, this may change back in time, when K record is ubiquitous. Still need to actually issue K record --- perl/DXChannel.pm | 1 + perl/DXProt.pm | 77 ++++++++++++++++-------- perl/DXProtHandle.pm | 136 +++++++++++++++++++++++++++---------------- perl/DXProtVars.pm | 2 +- perl/DXProtout.pm | 6 ++ perl/Version.pm | 2 +- 6 files changed, 150 insertions(+), 74 deletions(-) diff --git a/perl/DXChannel.pm b/perl/DXChannel.pm index 460eb525..7d340a61 100644 --- a/perl/DXChannel.pm +++ b/perl/DXChannel.pm @@ -122,6 +122,7 @@ $count = 0; do_pc9x => '9,Handles PC9x,yesno', inqueue => '9,Input Queue,parray', next_pc92_update => '9,Next PC92 Update,atime', + next_pc92_keepalive => '9,Next PC92 KeepAlive,atime', ); # object destruction diff --git a/perl/DXProt.pm b/perl/DXProt.pm index eec6b67b..41f1debe 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -46,6 +46,8 @@ use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restim $eph_pc15_restime $pc92_update_period $pc92_obs_timeout %pc92_find $pc92_find_timeout $pc92_short_update_period $next_pc92_obs_timeout $pc92_slug_changes $last_pc92_slug + $pc92_extnode_update_period $pc50_interval + $pc92_keepalive_period ); $pc11_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc11 @@ -73,13 +75,12 @@ $chatdupeage = 20 * 60; $chatimportfn = "$main::root/chat_import"; $investigation_int = 12*60*60; # time between checks to see if we can see this node $pc19_version = 5454; # the visible version no for outgoing PC19s generated from pc59 -$pc92_update_period = 60*60; # the period between outgoing PC92 C updates -$pc92_short_update_period = 15*60; # shorten the update period after a connection +$pc92_update_period = 24*60*60; # the period between outgoing PC92 C updates +$pc92_short_update_period = 15*60; # shorten the update period after a connection or start up +$pc92_extnode_update_period = 2*60*60; # the update period for external nodes +$pc92_keepalive_period = 60*60; # frequency of PC92 K (keepalive) records %pc92_find = (); # outstanding pc92 find operations $pc92_find_timeout = 30; # maximum time to wait for a reply -#$pc92_obs_timeout = $pc92_update_period; # the time between obscount countdowns -$pc92_obs_timeout = 60*60; # the time between obscount for incoming countdowns -$next_pc92_obs_timeout = $main::systime + 60*60; # the time between obscount countdowns @checklist = @@ -214,11 +215,19 @@ sub check sub update_pc92_next { my $self = shift; - my $period = shift || $pc92_update_period; + my $period = shift || ($self->{do_pc9x} ? $pc92_update_period : $pc92_extnode_update_period); $self->{next_pc92_update} = $main::systime + $period - int rand($period / 4); dbg("ROUTE: update_pc92_next: $self->{call} " . atime($self->{next_pc92_update})) if isdbg('obscount'); } +sub update_pc92_keepalive +{ + my $self = shift; + my $period = shift || $pc92_keepalive_period; + $self->{next_pc92_keepalive} = $main::systime + $period - int rand($period / 4); + dbg("ROUTE: update_pc92_keepalive: $self->{call} " . atime($self->{next_pc92_keepalive})) if isdbg('obscount'); +} + sub init { do "$main::data/hop_table.pl" if -e "$main::data/hop_table.pl"; @@ -239,7 +248,7 @@ sub init $main::me->{version} = $main::version; $main::me->{build} = "$main::subversion.$main::build"; $main::me->{do_pc9x} = 1; - $main::me->update_pc92_next($pc92_update_period); + $main::me->update_pc92_next($pc92_short_update_period); } # @@ -348,8 +357,12 @@ sub start my $script = new Script(lc $call) || new Script('node_default'); $script->run($self) if $script; - # set next_pc92_update time for this node sooner - $self->update_pc92_next($self->{outbound} ? $pc92_short_update_period : $pc92_update_period); + # set up a config broadcast "quite soon" to converge tables quicker + $main::me->update_pc92_next($pc92_short_update_period); + $self->update_pc92_next($pc92_short_update_period); + + # set next keepalive time + $self->update_pc92_keepalive; } # @@ -430,12 +443,6 @@ sub process my $dxchan; my $pc50s; - # send out a pc50 on EVERY channel all at once - if ($t >= $last_pc50 + $DXProt::pc50_interval) { - $pc50s = pc50($main::me, scalar DXChannel::get_all_users); - eph_dup($pc50s); - $last_pc50 = $t; - } foreach $dxchan (@dxchan) { next unless $dxchan->is_node; @@ -466,16 +473,20 @@ sub process if ($t - $last10 >= 10) { # clean out ephemera + eph_clean(); import_chat(); - if ($main::systime >= $next_pc92_obs_timeout) { + $last10 = $t; + + # send out a pc50 on EVERY channel all at once + if ($t >= $last_pc50 + $pc50_interval) { + $pc50s = pc50($main::me, scalar DXChannel::get_all_users); + eph_dup($pc50s); + $last_pc50 = $t; time_out_pc92_routes(); - $next_pc92_obs_timeout = $main::systime + $pc92_obs_timeout; } - $last10 = $t; - # send out config broadcasts foreach $dxchan (@dxchan) { next unless $dxchan->is_node; @@ -487,14 +498,32 @@ sub process # records. Someone will win, it does not really matter who, because # we always believe "us". if ($main::systime >= $dxchan->{next_pc92_update}) { - dbg("ROUTE: pc92 broadcast candidate: $dxchan->{call}") if isdbg('obscount'); if ($dxchan == $main::me || !$dxchan->{do_pc9x}) { + dbg("ROUTE: pc92 broadcast candidate: $dxchan->{call}") if isdbg('obscount'); my $ref = Route::Node::get($dxchan->{call}); - if ($dxchan == $main::me || ($ref && ($ref->measure_pc9x_t($main::systime-$main::systime_daystart)) >= $pc92_update_period/2)) { + if ($dxchan == $main::me || ($ref && ($ref->measure_pc9x_t($main::systime-$main::systime_daystart)) >= $pc92_extnode_update_period/2)) { $dxchan->broadcast_pc92_update($dxchan->{call}); } else { - $dxchan->update_pc92_next($pc92_update_period - rand($pc92_update_period/4)); + $dxchan->update_pc92_next; } + } else { + $dxchan->update_pc92_next; # this won't actually do anything, it's just to be tidy + } + } + + # do the keepalives in the same way, but use a different timer + if ($main::systime >= $dxchan->{next_pc92_keepalive}) { + if ($dxchan == $main::me || !$dxchan->{do_pc9x}) { + dbg("ROUTE: pc92 keepalive candidate: $dxchan->{call}") if isdbg('obscount'); + my $ref = Route::Node::get($dxchan->{call}); +# if ($dxchan == $main::me || ($ref && ($ref->measure_pc9x_t($main::systime-$main::systime_daystart)) >= $pc92_keepalive_period/2)) { +# $dxchan->broadcast_pc92_update($dxchan->{call}); +# } else { +# $dxchan->update_pc92_next($pc92_extnode_update_period); +# } +# } else { +# $dxchan->update_pc92_next; # this won't actually do anything, it's just to be tidy + $dxchan->update_pc92_keepalive; } } } @@ -936,7 +965,7 @@ sub broadcast_pc92_update my $l = $nref->last_PC92C(gen_my_pc92_config($nref)); $nref->lastid(last_pc9x_id()); $main::me->broadcast_route_pc9x($main::mycall, undef, $l, 0); - $self->update_pc92_next($pc92_update_period); + $self->update_pc92_next; } sub time_out_pc92_routes @@ -1462,11 +1491,13 @@ sub route_pc41 broadcast_route($self, $origin, \&pc41, $line, 1, @_); } +# this is probably obsolete now sub route_pc50 { my $self = shift; my $origin = shift; my $line = shift; + broadcast_route($self, $origin, \&pc50, $line, 1, @_); } diff --git a/perl/DXProtHandle.pm b/perl/DXProtHandle.pm index 4d69b1aa..96e62c70 100644 --- a/perl/DXProtHandle.pm +++ b/perl/DXProtHandle.pm @@ -132,6 +132,8 @@ sub handle_11 } } +# my ($hops) = $_[8] =~ /^H(\d+)/; + # is the spotted callsign blank? This should really be trapped earlier but it # could break other protocol sentences. Also check for lower case characters. if ($_[2] =~ /^\s*$/) { @@ -1210,6 +1212,8 @@ sub handle_50 my $line = shift; my $origin = shift; + return if (eph_dup($line)); + my $call = $_[1]; RouteDB::update($call, $self->{call}); @@ -1217,12 +1221,16 @@ sub handle_50 my $node = Route::Node::get($call); if ($node) { return unless $node->call eq $self->{call}; - $node->usercount($_[2]); + $node->usercount($_[2]) unless $node->users; + $node->reset_obs; # input filter if required - return unless $self->in_filter_route($node); +# return unless $self->in_filter_route($node); - $self->route_pc50($origin, $line, $node, $_[2], $_[3]) unless eph_dup($line); + unless ($self->{isolate}) { + DXChannel::broadcast_nodes($line, $self); # send it to everyone but me + } +# $self->route_pc50($origin, $line, $node, $_[2], $_[3]) unless eph_dup($line); } } @@ -1500,6 +1508,58 @@ sub check_pc9x_t return $parent; } +sub pc92_handle_first_slot +{ + my $self = shift; + my $slot = shift; + my $parent = shift; + my $t = shift; + my $oparent = $parent; + + my @radd; + + my ($call, $is_node, $is_extnode, $here, $version, $build) = @$slot; + if ($call && $is_node) { + if ($call eq $main::mycall) { + dbg("PCPROT: $call looped back onto $main::mycall, ignored") if isdbg('chanerr'); + return; + } + # this is only accepted from my "self". + # this also kills configs from PC92 nodes with external PC19 nodes that are also + # locally connected. Local nodes always take precedence. But we remember the lastid + # to try to reduce the number of dupe PC92s for this external node. + if (DXChannel::get($call) && $call ne $self->{call}) { + $parent = check_pc9x_t($call, $t, 92); # this will update the lastid time + dbg("PCPROT: locally connected node $call from other another node $self->{call}, ignored") if isdbg('chanerr'); + return; + } + if ($is_extnode) { + # reparent to external node (note that we must have received a 'C' or 'A' record + # from the true parent node for this external before we get one for the this node + unless ($parent = Route::Node::get($call)) { + if ($is_extnode && $oparent) { + @radd = _add_thingy($oparent, $slot); + $parent = $radd[0]; + } else { + dbg("PCPROT: no previous C or A for this external node received, ignored") if isdbg('chanerr'); + return; + } + } + $parent = check_pc9x_t($call, $t, 92) || return; + $parent->via_pc92(1); + $parent->PC92C_dxchan($self->{call}); + } + } else { + dbg("PCPROT: must be \$mycall or external node as first entry, ignored") if isdbg('chanerr'); + return; + } + $parent->here(Route::here($here)); + $parent->version($version || $pc19_version) if $version; + $parent->build($build) if $build && $build > $parent->build; + $parent->PC92C_dxchan($self->{call}) unless $self->{call} eq $parent->call; + return ($parent, @radd); +} + # DXSpider routing entries sub handle_92 { @@ -1585,6 +1645,22 @@ sub handle_92 } return; } + + } elsif ($sort eq 'K') { + # remember the last channel we arrived on + $parent->PC92C_dxchan($self->{call}) unless $self->{call} eq $parent->call; + + my @ent = _decode_pc92_call($_[4]); + + if (@ent) { + my $add; + + ($parent, $add) = $self->pc92_handle_first_slot($ent[0], $parent, $t); + return unless $parent; # dupe + + push @radd, $add if $add; + dbg("ROUTE: reset obscount on $parent->{call} now " . $parent->obscount) if isdbg('obscount'); + } } elsif ($sort eq 'A' || $sort eq 'D' || $sort eq 'C') { # remember the last channel we arrived on @@ -1612,46 +1688,13 @@ sub handle_92 # except in the case of 'A' or 'D' in which the $pcall is used # otherwise use the node call and update any information # that needs to be done. - my ($call, $is_node, $is_extnode, $here, $version, $build) = @{$ent[0]}; - if ($call && $is_node) { - if ($call eq $main::mycall) { - dbg("PCPROT: $call looped back onto $main::mycall, ignored") if isdbg('chanerr'); - return; - } - # this is only accepted from my "self". - # this also kills configs from PC92 nodes with external PC19 nodes that are also - # locally connected. Local nodes always take precedence. But we remember the lastid - # to try to reduce the number of dupe PC92s for this external node. - if (DXChannel::get($call) && $call ne $self->{call}) { - $parent = check_pc9x_t($call, $t, 92); # this will update the lastid time - dbg("PCPROT: locally connected node $call from other another node $self->{call}, ignored") if isdbg('chanerr'); - return; - } - if ($is_extnode) { - # reparent to external node (note that we must have received a 'C' or 'A' record - # from the true parent node for this external before we get one for the this node - unless ($parent = Route::Node::get($call)) { - if ($is_extnode && $oparent) { - @radd = _add_thingy($oparent, $ent[0]); - $parent = $radd[0]; - } else { - dbg("PCPROT: no previous C or A for this external node received, ignored") if isdbg('chanerr'); - return; - } - } - $parent = check_pc9x_t($call, $t, 92) || return; - $parent->via_pc92(1); - $parent->PC92C_dxchan($self->{call}); - } - } else { - dbg("PCPROT: must be \$mycall or external node as first entry, ignored") if isdbg('chanerr'); - return; - } - $parent->here(Route::here($here)); - $parent->version($version || $pc19_version) if $version; - $parent->build($build) if $build && $build > $parent->build; - $parent->PC92C_dxchan($self->{call}) unless $self->{call} eq $parent->call; + my $add; + + ($parent, $add) = $self->pc92_handle_first_slot($ent[0], $parent, $t); + return unless $parent; # dupe + shift @ent; + push @radd, $add if $add; } # do a pass through removing any references to either locally connected nodes or mycall @@ -1676,13 +1719,8 @@ sub handle_92 } elsif ($sort eq 'C') { my (@nodes, @users); - # we only reset obscounts on config records - $oparent->reset_obs; - dbg("ROUTE: reset obscount on $pcall now " . $oparent->obscount) if isdbg('obscount'); - if ($oparent != $parent) { - $parent->reset_obs; - dbg("ROUTE: reset obscount on $parent->{call} now " . $parent->obscount) if isdbg('obscount'); - } + # we reset obscounts on config records as well as K records + dbg("ROUTE: reset obscount on $parent->{call} now " . $parent->obscount) if isdbg('obscount'); # foreach my $r (@nent) { diff --git a/perl/DXProtVars.pm b/perl/DXProtVars.pm index ca1538d7..ae192bcf 100644 --- a/perl/DXProtVars.pm +++ b/perl/DXProtVars.pm @@ -12,7 +12,7 @@ package DXProt; # the interval between pc50s (in seconds) -$pc50_interval = 14*60; +$pc50_interval = 60*60; # the version of DX cluster (tm) software I am masquerading as $myprot_version = 5300; diff --git a/perl/DXProtout.pm b/perl/DXProtout.pm index 2325e7a5..ec9abaa0 100644 --- a/perl/DXProtout.pm +++ b/perl/DXProtout.pm @@ -416,6 +416,12 @@ sub pc92c return _gen_pc92('C', 1, @_); } +# send a keep alive +sub pc92k +{ + return _gen_pc92('K', 1, @_); +} + # send a 'find' message sub pc92f { diff --git a/perl/Version.pm b/perl/Version.pm index d3d3984e..b2ca6585 100644 --- a/perl/Version.pm +++ b/perl/Version.pm @@ -11,6 +11,6 @@ use vars qw($version $subversion $build); $version = '1.54'; $subversion = '0'; -$build = '144'; +$build = '145'; 1; -- 2.34.1