-# node connected list from neighbour
-sub handle_38
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
-}
-
-# incoming disconnect
-sub handle_39
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
- if ($_[1] eq $self->{call}) {
- $self->disconnect(1);
- } else {
- dbg("PCPROT: came in on wrong channel") if isdbg('chanerr');
- }
-}
-
-sub handle_40 {goto &handle_28}
-
-# user info
-sub handle_41
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
- my $call = $_[1];
-
- my $l = $line;
- $l =~ s/[\x00-\x20\x7f-\xff]+//g; # remove all funny characters and spaces for dup checking
- if (eph_dup($l, $eph_info_restime)) {
- dbg("PCPROT: dup PC41, ignored") if isdbg('chanerr');
- return;
- }
-
- # input filter if required
- # my $ref = Route::get($call) || Route->new($call);
- # return unless $self->in_filter_route($ref);
-
- if ($_[3] eq $_[2] || $_[3] =~ /^\s*$/) {
- dbg('PCPROT: invalid value') if isdbg('chanerr');
- return;
- }
-
- # add this station to the user database, if required
- my $user = DXUser->get_current($call);
- $user = DXUser->new($call) unless $user;
-
- if ($_[2] == 1) {
- $user->name($_[3]);
- } elsif ($_[2] == 2) {
- $user->qth($_[3]);
- } elsif ($_[2] == 3) {
- if (is_latlong($_[3])) {
- my ($lat, $long) = DXBearing::stoll($_[3]);
- $user->lat($lat);
- $user->long($long);
- $user->qra(DXBearing::lltoqra($lat, $long));
- } else {
- dbg('PCPROT: not a valid lat/long') if isdbg('chanerr');
- return;
- }
- } elsif ($_[2] == 4) {
- $user->homenode($_[3]);
- } elsif ($_[2] == 5) {
- if (is_qra(uc $_[3])) {
- my ($lat, $long) = DXBearing::qratoll(uc $_[3]);
- $user->lat($lat);
- $user->long($long);
- $user->qra(uc $_[3]);
- } else {
- dbg('PCPROT: not a valid QRA locator') if isdbg('chanerr');
- return;
- }
- }
- $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, $_[2], $_[3], $_[4]);
-}
-
-sub handle_42 {goto &handle_28}
-
-
-# database
-sub handle_44 {goto &handle_37}
-sub handle_45 {goto &handle_37}
-sub handle_46 {goto &handle_37}
-sub handle_47 {goto &handle_37}
-sub handle_48 {goto &handle_37}
-
-# message and database
-sub handle_49
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
-
- if (eph_dup($line)) {
- dbg("PCPROT: Dup PC49 ignored\n") if isdbg('chanerr');
- return;
- }
-
- if ($_[1] eq $main::mycall) {
- DXMsg::handle_49($self, @_);
- } else {
- $self->route($_[1], $line) unless $self->is_clx;
- }
-}
-
-# keep alive/user list
-sub handle_50
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
-
- my $call = $_[1];
- my $node = Route::Node::get($call);
- if ($node) {
- return unless $node->call eq $self->{call};
- $node->usercount($_[2]);
-
- # input filter if required
- return unless $self->in_filter_route($node);
-
- $self->route_pc50($node, $_[2], $_[3]) unless eph_dup($line);
- }
-}
-
-# incoming ping requests/answers
-sub handle_51
-{
- my $self = shift;
- my $pcno = shift;
- my $line = shift;
- my $to = $_[1];
- my $from = $_[2];
- my $flag = $_[3];
-
-
- # is it for us?
- if ($to eq $main::mycall) {
- if ($flag == 1) {
- $self->send(pc51($from, $to, '0'));
- } else {
- # it's a reply, look in the ping list for this one
- my $ref = $pings{$from};
- if ($ref) {
- my $tochan = DXChannel->get($from);
- while (@$ref) {
- my $r = shift @$ref;
- my $dxchan = DXChannel->get($r->{call});
- next unless $dxchan;
- my $t = tv_interval($r->{t}, [ gettimeofday ]);
- if ($dxchan->is_user) {
- my $s = sprintf "%.2f", $t;
- my $ave = sprintf "%.2f", $tochan ? ($tochan->{pingave} || $t) : $t;
- $dxchan->send($dxchan->msg('pingi', $from, $s, $ave))
- } elsif ($dxchan->is_node) {
- if ($tochan) {
- my $nopings = $tochan->user->nopings || 2;
- push @{$tochan->{pingtime}}, $t;
- shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6;
-
- # cope with a missed ping, this means you must set the pingint large enough
- if ($t > $tochan->{pingint} && $t < 2 * $tochan->{pingint} ) {
- $t -= $tochan->{pingint};
- }
-
- # calc smoothed RTT a la TCP
- if (@{$tochan->{pingtime}} == 1) {
- $tochan->{pingave} = $t;
- } else {
- $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6);
- }
- $tochan->{nopings} = $nopings; # pump up the timer
- }
- }
+ # send out config broadcasts
+ foreach $dxchan (@dxchan) {
+ next unless $dxchan->is_node;
+
+ # send out a PC92 config record if required for me and
+ # all my non pc9x dependent nodes. But for dependent nodes we only do
+ # this if we have not seen any from anyone else for at least half
+ # of one update period. This should stop quite a bit of excess C
+ # records. Someone will win, it does not really matter who, because
+ # we always believe "us".
+ if ($main::systime >= $dxchan->{next_pc92_update}) {
+ 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_extnode_update_period/2)) {
+ $dxchan->broadcast_pc92_update($dxchan->{call});
+ } else {
+ $dxchan->update_pc92_next;
+ }
+ } else {
+ $dxchan->update_pc92_next; # this won't actually do anything, it's just to be tidy