$user->lastin($main::systime) unless DXChannel::get($call);
$user->put;
}
- $self->route_pc16($origin, $line, $parent, @rout) if @rout;
-
+ if (@rout) {
+ $self->route_pc16($origin, $line, $parent, @rout);
+ $self->route_pc92a($main::mycall, undef, $parent, @rout);
+ }
}
# remove a user
$uref = Route->new($ucall) unless $uref; # throw away
$self->route_pc17($origin, $line, $parent, $uref);
+ $self->route_pc92d($main::mycall, undef, $parent, $uref);
}
# link request
if (@rout) {
$self->route_pc21($self->{call}, $line, @rout);
$self->route_pc19($self->{call}, $line, @rout);
- $self->route_pc92a($main::mycall, $line, @rout);
+ $self->route_pc92a($main::mycall, $line, $main::routeroot, @rout);
}
}
if (@rout) {
$self->route_pc21($origin, $line, @rout);
- $self->route_pc92d($main::mycall, $line, @rout);
+ $self->route_pc92d($main::mycall, $line, $main::routeroot, @rout);
}
}
my $call = $ref->call;
my $extra = '';
$flag |= $ref->here ? 1 : 0;
- if ($ext && ($ref->isa('Route::Node') || $ref->isa('DXProt'))) {
+ if ($ref->isa('Route::Node') || $ref->isa('DXProt')) {
$flag |= 4;
-# if ($ref->version || $ref->build) {
- if ($ref->version) {
- my $version = $ref->version || 1.0;
- $version = $version * 100 + 5300 if $version < 50;
- $extra .= ":" . $version;
-# $extra .= (":" . ($ref->build ? $ref->build : '')) if $ref->build;
+ my $dxchan = DXChannel::get($call);
+ $flag |= 2 if $call ne $main::mycall && $dxchan && !$dxchan->{do_pc92};
+ if ($ext) {
+ if ($ref->version) {
+ my $version = $ref->version || 1.0;
+ $version = $version * 100 + 5300 if $version < 50;
+ $extra .= ":" . $version;
+ }
}
}
return "$flag$call$extra";
$self->{do_pc92} ||= 1;
- my ($pcall, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_[1]);
+ my $pcall = $_[1];
unless ($pcall) {
dbg("PCPROT: invalid callsign string '$_[1]', ignored") if isdbg('chanerr');
return;
my $t = $_[2];
my $sort = $_[3];
+ my @ent = grep {$_ && /^[0-7]/} @_[4 .. $#_];
+
if ($pcall eq $main::mycall) {
dbg("PCPROT: looped back, ignored") if isdbg('chanerr');
return;
dbg("PCPROT: dup / old id <= $lastid, ignored") if isdbg('chanerr');
return;
}
- $parent->flags(Route::here($here));
- $parent->version($version) if $version;
} else {
- $parent = Route::Node->new($pcall, $version, Route::here($here));
+ $parent = Route::Node->new($pcall);
}
$parent->lastid->{92} = $t;
- $parent->build($build) if $build;
+ if (@ent) {
+ my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($ent[0]);
+ if ($call && $is_node && $call eq $pcall) {
+ $parent->here(Route::here($here));
+ $parent->version($version) if $version;
+ $parent->build($build) if $build;
+ } elsif ($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)) {
+ dbg("PCPROT: no previous C or A for this external node received, ignored") if isdbg('chanerr');
+ return;
+ }
+ } else {
+ dbg("PCPROT: must be mycall or external node as first entry, ignored") if isdbg('chanerr');
+ return;
+ }
+ shift @ent;
+ }
+
+ my (@radd, @rdel);
+
if ($sort eq 'A') {
- if ($_[4]) {
- _add_thingy($parent, $_[4]);
+ for (@ent) {
+ push @radd, _add_thingy($parent, $_);
}
} elsif ($sort eq 'D') {
- if ($_[4]) {
- _del_thingy($parent, $_[4]);
+ for (@ent) {
+ push @rdel, _del_thingy($parent, $_);
}
} elsif ($sort eq 'C') {
- my $i;
- $parent->del_nodes;
- $parent->_del_users;
- for ($i = 4; $_[$i]; $i++) {
- _add_thingy($parent, $_[$i]);
+ my (@nodes, @users);
+ for (@ent) {
+ my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_);
+ if ($call) {
+ if ($is_node) {
+ push @nodes, $call;
+ } else {
+ push @users, $call;
+ }
+ } else {
+ dbg("DXPROT: pc92 call entry '$_' not decoded, ignored") if isdbg('chanerr');
+ }
+ }
+
+ my ($dnodes, $dusers, $nnodes, $nusers) = $parent->calc_config_changes(\@nodes, \@users);
+
+ for (@ent) {
+ my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_);
+ if ($call) {
+ push @radd,_add_thingy($parent, $_) if grep $call eq $_, (@$nnodes, @$nusers);
+ push @rdel,_del_thingy($parent, $_) if grep $call eq $_, (@$dnodes, @$dusers);
+ }
}
} else {
dbg("PCPROT: unknown action '$sort', ignored") if isdbg('chanerr');
+ return;
+ }
+
+ $self->broadcast_route_pc9x($pcall, undef, $line, 0);
+ foreach my $r (@rdel) {
+ next unless $r;
+
+ $self->route_pc21($pcall, undef, $r) if $r->isa('Route::Node');
+ $self->route_pc17($pcall, undef, $parent, $r) if $r->isa('Route::User');
+ }
+ foreach my $r (@radd) {
+ next unless $r;
+
+ $self->route_pc19($pcall, undef, $r) if $r->isa('Route::Node');
+ $self->route_pc16($pcall, undef, $parent, $r) if $r->isa('Route::User');
}
}