X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXProt.pm;h=03405a086e984b36cc5e312f0aac40bf19804cd8;hb=refs%2Fremotes%2Fserver%2Fspider2;hp=25e98cc4786d62b829df57e7e0a119906ae1a4b2;hpb=f726c14c2f603c02eabecc4526e588354a3a7e0b;p=spider.git diff --git a/perl/DXProt.pm b/perl/DXProt.pm index 25e98cc4..03405a08 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -33,12 +33,13 @@ use DXHash; use Route; use Route::Node; use Script; +use Thingy; 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,0)); +$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/,(0,0)); $main::build += $VERSION; $main::branch += $BRANCH; @@ -74,48 +75,48 @@ $chatdupeage = 20 * 60 * 60; @checklist = ( - [ qw(c c m bp bc c) ], # pc10 - [ qw(f m d t m c c h) ], # pc11 - [ qw(c bm m bm bm p h) ], # pc12 - [ qw(c h) ], # - [ qw(c h) ], # - [ qw(c m h) ], # + [ qw(i c c m bp bc c) ], # pc10 + [ qw(i f m d t m c c h) ], # pc11 + [ qw(i c bm m bm bm p h) ], # pc12 + [ qw(i c h) ], # + [ qw(i c h) ], # + [ qw(i c m h) ], # undef , # pc16 has to be validated manually - [ qw(c c h) ], # pc17 - [ qw(m n) ], # pc18 + [ qw(i c c h) ], # pc17 + [ qw(i m n) ], # pc18 undef , # pc19 has to be validated manually undef , # pc20 no validation - [ qw(c m h) ], # pc21 + [ qw(i c m h) ], # pc21 undef , # pc22 no validation - [ qw(d n n n n m c c h) ], # pc23 - [ qw(c p h) ], # pc24 - [ qw(c c n n) ], # pc25 - [ qw(f m d t m c c bc) ], # pc26 - [ qw(d n n n n m c c bc) ], # pc27 - [ qw(c c m c d t p m bp n p bp bc) ], # pc28 - [ qw(c c n m) ], # pc29 - [ qw(c c n) ], # pc30 - [ qw(c c n) ], # pc31 - [ qw(c c n) ], # pc32 - [ qw(c c n) ], # pc33 - [ qw(c c m) ], # pc34 - [ qw(c c m) ], # pc35 - [ qw(c c m) ], # pc36 - [ qw(c c n m) ], # pc37 + [ qw(i d n n n n m c c h) ], # pc23 + [ qw(i c p h) ], # pc24 + [ qw(i c c n n) ], # pc25 + [ qw(i f m d t m c c bc) ], # pc26 + [ qw(i d n n n n m c c bc) ], # pc27 + [ qw(i c c m c d t p m bp n p bp bc) ], # pc28 + [ qw(i c c n m) ], # pc29 + [ qw(i c c n) ], # pc30 + [ qw(i c c n) ], # pc31 + [ qw(i c c n) ], # pc32 + [ qw(i c c n) ], # pc33 + [ qw(i c c m) ], # pc34 + [ qw(i c c m) ], # pc35 + [ qw(i c c m) ], # pc36 + [ qw(i c c n m) ], # pc37 undef, # pc38 not interested - [ qw(c m) ], # pc39 - [ qw(c c m p n) ], # pc40 - [ qw(c n m h) ], # pc41 - [ qw(c c n) ], # pc42 + [ qw(i c m) ], # pc39 + [ qw(i c c m p n) ], # pc40 + [ qw(i c n m h) ], # pc41 + [ qw(i c c n) ], # pc42 undef, # pc43 don't handle it - [ qw(c c n m m c) ], # pc44 - [ qw(c c n m) ], # pc45 - [ qw(c c n) ], # pc46 + [ qw(i c c n m m c) ], # pc44 + [ qw(i c c n m) ], # pc45 + [ qw(i c c n) ], # pc46 undef, # pc47 undef, # pc48 - [ qw(c m h) ], # pc49 - [ qw(c n h) ], # pc50 - [ qw(c c n) ], # pc51 + [ qw(i c m h) ], # pc49 + [ qw(i c n h) ], # pc50 + [ qw(i c c n) ], # pc51 undef, undef, undef, @@ -137,7 +138,7 @@ $chatdupeage = 20 * 60 * 60; undef, # pc70 undef, undef, - [ qw(d n n n n n n m m m c c h) ], # pc73 + [ qw(i d n n n n n n m m m c c h) ], # pc73 undef, undef, undef, @@ -148,8 +149,13 @@ $chatdupeage = 20 * 60 * 60; undef, undef, undef, - [ qw(c c c m) ], # pc84 - [ qw(c c c m) ], # pc85 + [ qw(i c c c m) ], # pc84 + [ qw(i c c c m) ], # pc85 + undef, + undef, + undef, + undef, + [ qw(i c n) ], # pc90 ); # use the entry in the check list to check the field list presented @@ -163,28 +169,29 @@ sub check return 0 unless ref $ref; my $i; - shift; # not interested in the first field - for ($i = 0; $i < @$ref; $i++) { + for ($i = 1; $i < @$ref; $i++) { my ($blank, $act) = $$ref[$i] =~ /^(b?)(\w)$/; return 0 unless $act; next if $blank && $_[$i] =~ /^[ \*]$/; if ($act eq 'c') { - return $i+1 unless is_callsign($_[$i]); + return $i unless is_callsign($_[$i]); + } elsif ($act eq 'i') { + ; # do nothing } elsif ($act eq 'm') { - return $i+1 unless is_pctext($_[$i]); + return $i unless is_pctext($_[$i]); } elsif ($act eq 'p') { - return $i+1 unless is_pcflag($_[$i]); + return $i unless is_pcflag($_[$i]); } elsif ($act eq 'f') { - return $i+1 unless is_freq($_[$i]); + return $i unless is_freq($_[$i]); } elsif ($act eq 'n') { - return $i+1 unless $_[$i] =~ /^[\d ]+$/; + return $i unless $_[$i] =~ /^[\d ]+$/; } elsif ($act eq 'h') { - return $i+1 unless $_[$i] =~ /^H\d\d?$/; + return $i unless $_[$i] =~ /^H\d\d?$/; } elsif ($act eq 'd') { - return $i+1 unless $_[$i] =~ /^\s*\d+-\w\w\w-[12][90]\d\d$/; + return $i unless $_[$i] =~ /^\s*\d+-\w\w\w-[12][90]\d\d$/; } elsif ($act eq 't') { - return $i+1 unless $_[$i] =~ /^[012]\d[012345]\dZ$/; - } + return $i unless $_[$i] =~ /^[012]\d[012345]\dZ$/; + } } return 0; } @@ -295,6 +302,16 @@ sub sendinit $self->send(pc18()); } + +sub send +{ + my $self = shift; + while (@_) { + my $line = shift; + $self->SUPER::send($line); + } +} + # # This is the normal pcxx despatcher # @@ -311,8 +328,10 @@ sub normal # process PC frames, this will fail unless the frame starts PCnn my ($pcno) = $field[0] =~ /^PC(\d\d)/; # just get the number - return unless $pcno; - return if $pcno < 10 || $pcno > 99; + unless (defined $pcno && $pcno >= 10 && $pcno <= 99) { + dbg("PCPROT: unknown protocol") if isdbg('chanerr'); + return; + } # check for and dump bad protocol messages my $n = check($pcno, @field); @@ -321,20 +340,15 @@ sub normal return; } - # local processing 1 - my $pcr; - eval { - $pcr = Local::pcprot($self, $pcno, @field); - }; -# dbg("Local::pcprot error $@") if isdbg('local') if $@; - return if $pcr; - + my $origin = $self->{call}; + no strict 'subs'; my $sub = "handle_$pcno"; + if ($self->can($sub)) { - $self->$sub($pcno, $line, @field); + $self->$sub($pcno, $line, $origin, @field); } else { - $self->handle_default($pcno, $line, @field); + $self->handle_default($pcno, $line, $origin, @field); } } @@ -344,8 +358,9 @@ sub handle_10 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; - # rsfp check + # rsfp check return if $rspfcheck and !$self->rspfcheck(0, $_[6], $_[1]); # will we allow it at all? @@ -425,6 +440,7 @@ sub handle_11 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; # route 'foreign' pc26s if ($pcno == 26) { @@ -577,6 +593,7 @@ sub handle_12 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; # return if $rspfcheck and !$self->rspfcheck(1, $_[5], $_[1]); @@ -607,7 +624,7 @@ sub handle_12 my $dxchan; - if ((($dxchan = DXChannel->get($_[2])) && $dxchan->is_user) || $_[4] =~ /^[\#\w]+$/){ + if ((($dxchan = DXChannel->get($_[2])) && $dxchan->is_user) || $_[4] =~ /^[\#\w.]+$/){ $self->send_chat($line, @_[1..6]); } elsif ($_[2] eq '*' || $_[2] eq $main::mycall) { @@ -645,7 +662,7 @@ sub handle_16 my $self = shift; my $pcno = shift; my $line = shift; - + my $origin = shift; if (eph_dup($line)) { dbg("PCPROT: dup PC16 detected") if isdbg('chanerr'); @@ -653,9 +670,7 @@ sub handle_16 } # general checks - my $dxchan; my $ncall = $_[1]; - my $newline = "PC16^"; # do I want users from this channel? unless ($self->user->wantpc16) { @@ -667,121 +682,27 @@ sub handle_16 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) { - my $nl = $pc19list{$ncall}; - - if ($nl && @_ > 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: PC19 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); - unless ($parent) { - dbg("PCPROT: lost $ncall after sending PC19 for it?"); - return; - } - } 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; + # is it connected directly to me? + if ($ncall eq $self->{call}) { + my @users; + for (my $i = 2; $i < $#_; $i++) { + my ($call, $conf, $here) = $_[$i] =~ /^(\S+) (\S) (\d)/o; + next unless $call && $conf && defined $here && is_callsign($call); + next if $call eq $main::mycall; + push @users, "$here$call"; } - # input filter if required - return unless $self->in_filter_route($parent); - } - - my $i; - my @rout; - for ($i = 2; $i < $#_; $i++) { - my ($call, $conf, $here) = $_[$i] =~ /^(\S+) (\S) (\d)/o; - next unless $call && $conf && defined $here && is_callsign($call); - next if $call eq $main::mycall; - - eph_del_regex("^PC17\\^$call\\^$ncall"); - - $conf = $conf eq '*'; - - # reject this if we think it is a node already - my $r = Route::Node::get($call); - my $u = DXUser->get_current($call) unless $r; - if ($r || ($u && $u->is_node)) { - dbg("PCPROT: $call is a node") if isdbg('chanerr'); - next; - } - - $r = Route::User::get($call); - my $flags = Route::here($here)|Route::conf($conf); - - if ($r) { - my $au = $r->addparent($parent); - if ($r->flags != $flags) { - $r->flags($flags); - $au = $r; - } - push @rout, $r if $au; + if (@users) { + my $t = Thingy::Route->new_user_connection($ncall, $ncall, @users); + $t->{_pcline} = [$line]; + $t->queue; } else { - push @rout, $parent->add_user($call, $flags); + dbg("PCPROT: no valid users, dropped") if isdbg('chanerr'); } - - - # add this station to the user database, if required - $call =~ s/-\d+$//o; # remove ssid for users - my $user = DXUser->get_current($call); - $user = DXUser->new($call) if !$user; - $user->homenode($parent->call) if !$user->homenode; - $user->node($parent->call); - $user->lastin($main::systime) unless DXChannel->get($call); - $user->put; + } else { + dbg("PCPROT: non-local PC16, dropped") if isdbg('chanerr'); } - - $self->route_pc16($parent, @rout) if @rout; } # remove a user @@ -790,6 +711,7 @@ sub handle_17 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $dxchan; my $ncall = $_[2]; my $ucall = $_[1]; @@ -801,39 +723,21 @@ sub handle_17 dbg("PCPROT: don't send users to $self->{call}") if isdbg('chanerr'); return; } + + # ignore PC17 addressed from me if ($ncall eq $main::mycall) { dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); return; } - my $uref = Route::User::get($ucall); - unless ($uref) { - dbg("PCPROT: Route::User $ucall not in config") if isdbg('chanerr'); - return; - } - my $parent = Route::Node::get($ncall); - unless ($parent) { - dbg("PCPROT: Route::Node $ncall not in config") if isdbg('chanerr'); - return; - } - - $dxchan = $parent->dxchan; - if ($dxchan && $dxchan ne $self) { - dbg("PCPROT: PC17 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); - - $parent->del_user($uref); - - if (eph_dup($line)) { - dbg("PCPROT: dup PC17 detected") if isdbg('chanerr'); - return; + # is it connected directly to me? + if ($ncall eq $self->{call}) { + my $t = Thingy::Route->new_user_disconnection($ncall, $ncall, $ucall); + $t->{_pcline} = [$line]; + $t->queue; + } else { + dbg("PCPROT: non-local PC17, dropped") if isdbg('chanerr'); } - - $self->route_pc17($parent, $uref); } # link request @@ -842,31 +746,37 @@ sub handle_18 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; $self->state('init'); # record the type and version offered if ($_[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); + $self->version($1); + $self->user->version($1); + $self->build($2); + $self->user->build($2); unless ($self->is_spider) { $self->user->sort('S'); $self->user->put; $self->sort('S'); } } else { - $self->version(50.0); - $self->version($_[2] / 100) if $_[2] && $_[2] =~ /^\d+$/; + $self->version(0.5000); + $self->version("0.$_[2]") if $_[2] && $_[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; - $self->route_pc21(@rout, $parent) if @rout; - $self->send_local_config(); - $self->send(pc20()); + if ($self->version >= 2.0 && $self->version < 5) { + $self = bless $self, 'QXProt' unless $self->isa('QXProt'); + $self->sendinit; + } else { + # first clear out any nodes on this dxchannel + my $parent = Route::Node::get($self->{call}); + my @rout = $parent->del_nodes; + $self->route_pc21($origin, $line, @rout, $parent) if @rout; + $self->send_local_config(); + $self->send(pc20()); + } } # incoming cluster list @@ -875,26 +785,15 @@ sub handle_19 my $self = shift; my $pcno = shift; my $line = shift; - - my $i; - my $newline = "PC19^"; + my $origin = shift; if (eph_dup($line)) { dbg("PCPROT: dup PC19 detected") if isdbg('chanerr'); return; } - # new routing list - my @rout; - my $parent = Route::Node::get($self->{call}); - unless ($parent) { - dbg("DXPROT: my parent $self->{call} has disappeared"); - $self->disconnect; - return; - } - # parse the PC19 - for ($i = 1; $i < $#_-1; $i += 4) { + for (my $i = 1; $i < $#_-1; $i += 4) { my $here = $_[$i]; my $call = uc $_[$i+1]; my $conf = $_[$i+2]; @@ -904,77 +803,16 @@ sub handle_19 eph_del_regex("^PC(?:21\\^$call|17\\^[^\\^]+\\^$call)"); # check for sane parameters - # $ver = 5000 if $ver eq '0000'; next if $ver < 5000; # only works with version 5 software - next if length $call < 3; # min 3 letter callsigns next if $call eq $main::mycall; - # check that this PC19 isn't trying to alter the wrong dxchan - 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'); - 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); - } - - 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) { - if ($self->in_filter_route($r)) { - $ar = $parent->add($call, $ver, $flags); - push @rout, $ar if $ar; - } else { - next; - } - } - if ($r->version ne $ver || $r->flags != $flags) { - $r->version($ver); - $r->flags($flags); - push @rout, $r unless $ar; - } - } else { - - # 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); - $user->wantroutepc19(1) unless defined $user->wantroutepc19; - push @rout, $ar if $ar; - } else { - next; - } - } else { - $pc19list{$call} = [] unless exists $pc19list{$call}; - my $nl = $pc19list{$call}; - push @{$pc19list{$call}}, [$self->{call}, $ver, $flags] unless grep $_->[0] eq $self->{call}, @$nl; - } + if ($call eq $self->{call}) { + my $t = Thingy::Route->new_node_connection($main::mycall, $call, "$here$call"); + $t->{v} = $ver; + $t->queue; + last; } - - # unbusy and stop and outgoing mail (ie if somehow we receive another PC19 without a disconnect) - my $mref = DXMsg::get_busy($call); - $mref->stop_msg($call) if $mref; - - $user->lastin($main::systime) unless DXChannel->get($call); - $user->put; } - - - $self->route_pc19(@rout) if @rout; } # send local configuration @@ -983,6 +821,7 @@ sub handle_20 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; $self->send_local_config(); $self->send(pc22()); $self->state('normal'); @@ -995,6 +834,7 @@ sub handle_21 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = uc $_[1]; eph_del_regex("^PC1[679].*$call"); @@ -1005,44 +845,6 @@ sub handle_21 $self->disconnect(1); return; } - - # 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; - 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; - } - 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); - } - } else { - dbg("PCPROT: I WILL _NOT_ be disconnected!") if isdbg('chanerr'); - return; - } - } - - $self->route_pc21(@rout) if @rout; } @@ -1051,6 +853,7 @@ sub handle_22 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; $self->state('normal'); $self->{lastping} = 0; } @@ -1061,8 +864,9 @@ sub handle_23 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; - # route 'foreign' pc27s + # route foreign' pc27s if ($pcno == 27) { if ($_[8] ne $main::mycall) { $self->route($_[8], $line); @@ -1111,6 +915,7 @@ sub handle_24 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = uc $_[1]; my ($nref, $uref); $nref = Route::Node::get($call); @@ -1127,7 +932,7 @@ sub handle_24 my $ref = $nref || $uref; return unless $self->in_filter_route($ref); - $self->route_pc24($ref, $_[3]); + $self->route_pc24($origin, $line, $ref, $_[3]); } # merge request @@ -1136,6 +941,7 @@ sub handle_25 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if ($_[1] ne $main::mycall) { $self->route($_[1], $line); return; @@ -1175,6 +981,7 @@ sub handle_28 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if ($_[1] eq $main::mycall) { no strict 'refs'; my $sub = "DXMsg::handle_$pcno"; @@ -1195,6 +1002,7 @@ sub handle_34 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if (eph_dup($line, $eph_pc34_restime)) { dbg("PCPROT: dupe PC34, ignored") if isdbg('chanerr'); } else { @@ -1208,6 +1016,7 @@ sub handle_35 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; eph_del_regex("^PC35\\^$_[2]\\^$_[1]\\^"); $self->process_rcmd_reply($_[1], $_[2], $_[1], $_[3]); } @@ -1220,7 +1029,14 @@ sub handle_37 my $self = shift; my $pcno = shift; my $line = shift; - DXDb::process($self, $line); + my $origin = shift; + if ($_[1] eq $main::mycall) { + no strict 'refs'; + my $sub = "DXDb::handle_$pcno"; + &$sub($self, @_); + } else { + $self->route($_[1], $line) unless $self->is_clx; + } } # node connected list from neighbour @@ -1229,6 +1045,7 @@ sub handle_38 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; } # incoming disconnect @@ -1237,6 +1054,7 @@ sub handle_39 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if ($_[1] eq $self->{call}) { $self->disconnect(1); } else { @@ -1252,6 +1070,7 @@ sub handle_41 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = $_[1]; my $l = $line; @@ -1328,6 +1147,7 @@ sub handle_49 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if (eph_dup($line)) { dbg("PCPROT: Dup PC49 ignored\n") if isdbg('chanerr'); @@ -1347,6 +1167,7 @@ sub handle_50 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = $_[1]; my $node = Route::Node::get($call); @@ -1357,7 +1178,7 @@ sub handle_50 # input filter if required return unless $self->in_filter_route($node); - $self->route_pc50($node, $_[2], $_[3]) unless eph_dup($line); + $self->route_pc50($origin, $line, $node, $_[2], $_[3]) unless eph_dup($line); } } @@ -1367,6 +1188,7 @@ sub handle_51 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $to = $_[1]; my $from = $_[2]; my $flag = $_[3]; @@ -1392,7 +1214,7 @@ sub handle_51 $dxchan->send($dxchan->msg('pingi', $from, $s, $ave)) } elsif ($dxchan->is_node) { if ($tochan) { - my $nopings = $tochan->user->nopings || 2; + my $nopings = $tochan->user->nopings || $obscount; push @{$tochan->{pingtime}}, $t; shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6; @@ -1429,6 +1251,7 @@ sub handle_75 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = $_[1]; if ($call ne $main::mycall) { $self->route($call, $line); @@ -1441,6 +1264,7 @@ sub handle_73 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; my $call = $_[1]; # do some de-duping @@ -1474,6 +1298,7 @@ sub handle_84 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; $self->process_rcmd($_[1], $_[2], $_[3], $_[4]); } @@ -1483,9 +1308,10 @@ sub handle_85 my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; $self->process_rcmd_reply($_[1], $_[2], $_[3], $_[4]); } - + # if get here then rebroadcast the thing with its Hop count decremented (if # there is one). If it has a hop count and it decrements to zero then don't # rebroadcast it. @@ -1499,12 +1325,13 @@ sub handle_default my $self = shift; my $pcno = shift; my $line = shift; + my $origin = shift; if (eph_dup($line)) { dbg("PCPROT: Ephemeral dup, dropped") if isdbg('chanerr'); } else { unless ($self->{isolate}) { - DXChannel::broadcast_nodes($line, $self); # send it to everyone but me + DXChannel::broadcast_nodes($line, $self) if $line =~ /\^H\d+\^?~?$/; # send it to everyone but me } } } @@ -1531,7 +1358,7 @@ sub process next unless $dxchan->is_node(); next if $dxchan == $main::me; - # send the pc50 or PC90 + # send the pc50 $dxchan->send($pc50s) if $pc50s; # send a ping out on this channel @@ -1603,7 +1430,8 @@ sub send_prot_line { my ($self, $filter, $hops, $isolate, $line) = @_; my $routeit; - + + if ($hops) { $routeit = $line; $routeit =~ s/\^H\d+\^\~$/\^H$hops\^\~/; @@ -1649,7 +1477,6 @@ sub send_wwv_spot $dxchan->wwv($line, $self->{isolate}, @_, $self->{call}, $wwv_dxcc, $wwv_itu, $wwv_cq, $org_dxcc, $org_itu, $org_cq); } - } sub wwv @@ -1798,7 +1625,13 @@ sub send_chat my $dxchan; my $target = $_[3]; my $text = unpad($_[2]); + my $ak1a_line; + # munge the group and recast the line if required + if ($target =~ s/\.LST$//) { + $ak1a_line = $line; + } + # obtain country codes etc my ($ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq) = (0..0); my ($ann_state, $org_state) = ("", ""); @@ -1839,10 +1672,19 @@ sub send_chat # send it if it isn't the except list and isn't isolated and still has a hop count # taking into account filtering and so on foreach $dxchan (@dxchan) { - next if $dxchan == $main::me; - next if $dxchan == $self && $self->is_node; - next if $target eq 'LOCAL' && $dxchan->is_node; - $dxchan->chat($line, $self->{isolate}, $target, $_[1], $text, @_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq); + my $is_ak1a = $dxchan->is_ak1a; + + if ($dxchan->is_node) { + next if $dxchan == $main::me; + next if $dxchan == $self; + next unless $dxchan->is_spider || $is_ak1a; + next if $target eq 'LOCAL'; + if (!$ak1a_line && $is_ak1a) { + $ak1a_line = DXProt::pc12($_[0], $text, $_[1], "$target.LST"); + } + } + + $dxchan->chat($is_ak1a ? $ak1a_line : $line, $self->{isolate}, $target, $_[1], $text, @_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq); } } @@ -1882,29 +1724,36 @@ sub send_local_config # send our nodes if ($self->{isolate}) { @localnodes = ( $main::routeroot ); + $self->send_route($main::mycall, \&pc19, 1, $main::routeroot); } else { # create a list of all the nodes that are not connected to this connection # and are not themselves isolated, this to make sure that isolated nodes # don't appear outside of this node + + # send locally connected nodes my @dxchan = grep { $_->call ne $main::mycall && $_ != $self && !$_->{isolate} } DXChannel::get_all_nodes(); @localnodes = map { my $r = Route::Node::get($_->{call}); $r ? $r : () } @dxchan if @dxchan; - my @intcalls = map { $_->nodes } @localnodes if @localnodes; + $self->send_route($main::mycall, \&pc19, scalar(@localnodes)+1, $main::routeroot, @localnodes); + + my $node; + my @rawintcalls = map { $_->nodes } @localnodes if @localnodes; + my @intcalls; + for $node (@rawintcalls) { + push @intcalls, $node unless grep $node eq $_, @intcalls; + } my $ref = Route::Node::get($self->{call}); my @rnodes = $ref->nodes; - for my $node (@intcalls) { - push @remotenodes, Route::Node::get($node) unless grep $node eq $_, @rnodes; + for $node (@intcalls) { + push @remotenodes, Route::Node::get($node) unless grep $node eq $_, @rnodes, @remotenodes; } - unshift @localnodes, $main::routeroot; + $self->send_route($main::mycall, \&pc19, scalar(@remotenodes), @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 $node (@localnodes, @remotenodes) { + foreach $node ($main::routeroot, @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; + $self->send_route($main::mycall, \&pc16, 1, $node, @rout) if @rout && $self->user->wantsendpc16; } else { dbg("sent a null value") if isdbg('chanerr'); } @@ -2160,7 +2009,7 @@ sub disconnect # broadcast to all other nodes that all the nodes connected to via me are gone unless ($pc39flag && $pc39flag == 2) { - $self->route_pc21(@rout) if @rout; + $self->route_pc21($main::mycall, undef, @rout) if @rout; } # remove outstanding pings @@ -2192,9 +2041,11 @@ sub talk # send it if it isn't the except list and isn't isolated and still has a hop count # taking into account filtering and so on + sub send_route { my $self = shift; + my $origin = shift; my $generate = shift; my $no = shift; # the no of things to filter on my $routeit; @@ -2229,6 +2080,7 @@ sub send_route $routeit = adjust_hops($self, $line); # adjust its hop count by node name next unless $routeit; } + $self->send($routeit); } } @@ -2237,10 +2089,11 @@ sub send_route sub broadcast_route { my $self = shift; + my $origin = shift; my $generate = shift; + my $line = shift; my @dxchan = DXChannel::get_all_nodes(); my $dxchan; - my $line; unless ($self->{isolate}) { foreach $dxchan (@dxchan) { @@ -2249,7 +2102,7 @@ sub broadcast_route next unless $dxchan->isa('DXProt'); next if ($generate == \&pc16 || $generate==\&pc17) && !$dxchan->user->wantsendpc16; - $dxchan->send_route($generate, @_); + $dxchan->send_route($origin, $generate, @_); } } } @@ -2258,50 +2111,58 @@ sub route_pc16 { my $self = shift; return unless $self->user->wantpc16; - broadcast_route($self, \&pc16, 1, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc16, $line, 1, @_); } sub route_pc17 { my $self = shift; return unless $self->user->wantpc16; - broadcast_route($self, \&pc17, 1, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc17, $line, 1, @_); } sub route_pc19 { my $self = shift; - broadcast_route($self, \&pc19, scalar @_, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc19, $line, scalar @_, @_); } sub route_pc21 { my $self = shift; - broadcast_route($self, \&pc21, scalar @_, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc21, $line, scalar @_, @_); } sub route_pc24 { my $self = shift; - broadcast_route($self, \&pc24, 1, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc24, $line, 1, @_); } sub route_pc41 { my $self = shift; - broadcast_route($self, \&pc41, 1, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc41, $line, 1, @_); } sub route_pc50 { my $self = shift; - broadcast_route($self, \&pc50, 1, @_); -} - -sub route_pc90 -{ - my $self = shift; - broadcast_route($self, \&pc90, 1, @_); + my $origin = shift; + my $line = shift; + broadcast_route($self, $origin, \&pc50, $line, 1, @_); } sub in_filter_route