+ # send a ping out on this channel
+ if ($dxchan->{pingint} && $t >= $dxchan->{pingint} + $dxchan->{lastping}) {
+ if ($dxchan->{nopings} <= 0) {
+ $dxchan->disconnect;
+ } else {
+ addping($main::mycall, $dxchan->call);
+ $dxchan->{nopings} -= 1;
+ $dxchan->{lastping} = $t;
+ }
+ }
+ }
+
+ # every ten seconds
+ if ($t - $last10 >= 10) {
+ # clean out ephemera
+
+ eph_clean();
+
+ $last10 = $t;
+ }
+
+ if ($main::systime - 3600 > $last_hour) {
+ $last_hour = $main::systime;
+ }
+}
+
+#
+# finish up a pc context
+#
+
+#
+# some active measures
+#
+
+
+sub send_dx_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel->get_all();
+ my $dxchan;
+
+ # 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;
+ $dxchan->dx_spot($line, $self->{isolate}, @_, $self->{call});
+ }
+}
+
+sub dx_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{spotsfilter}) {
+ ($filter, $hops) = $self->{spotsfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line);
+}
+
+sub send_prot_line
+{
+ my ($self, $filter, $hops, $isolate, $line) = @_;
+ my $routeit;
+
+
+ if ($hops) {
+ $routeit = $line;
+ $routeit =~ s/\^H\d+\^\~$/\^H$hops\^\~/;
+ } else {
+ $routeit = adjust_hops($self, $line); # adjust its hop count by node name
+ return unless $routeit;
+ }
+ if ($filter) {
+ $self->send($routeit);
+ } else {
+ $self->send($routeit) unless $self->{isolate} || $isolate;
+ }
+}
+
+
+sub send_wwv_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel->get_all();
+ my $dxchan;
+ my ($wwv_dxcc, $wwv_itu, $wwv_cq, $org_dxcc, $org_itu, $org_cq) = (0..0);
+ my @dxcc = Prefix::extract($_[6]);
+ if (@dxcc > 0) {
+ $wwv_dxcc = $dxcc[1]->dxcc;
+ $wwv_itu = $dxcc[1]->itu;
+ $wwv_cq = $dxcc[1]->cq;
+ }
+ @dxcc = Prefix::extract($_[7]);
+ if (@dxcc > 0) {
+ $org_dxcc = $dxcc[1]->dxcc;
+ $org_itu = $dxcc[1]->itu;
+ $org_cq = $dxcc[1]->cq;
+ }
+
+ # 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;
+ my $routeit;
+ my ($filter, $hops);
+
+ $dxchan->wwv($line, $self->{isolate}, @_, $self->{call}, $wwv_dxcc, $wwv_itu, $wwv_cq, $org_dxcc, $org_itu, $org_cq);
+ }
+
+}
+
+sub wwv
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{wwvfilter}) {
+ ($filter, $hops) = $self->{wwvfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line)
+}
+
+sub send_wcy_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel->get_all();
+ my $dxchan;
+ my ($wcy_dxcc, $wcy_itu, $wcy_cq, $org_dxcc, $org_itu, $org_cq) = (0..0);
+ my @dxcc = Prefix::extract($_[10]);
+ if (@dxcc > 0) {
+ $wcy_dxcc = $dxcc[1]->dxcc;
+ $wcy_itu = $dxcc[1]->itu;
+ $wcy_cq = $dxcc[1]->cq;
+ }
+ @dxcc = Prefix::extract($_[11]);
+ if (@dxcc > 0) {
+ $org_dxcc = $dxcc[1]->dxcc;
+ $org_itu = $dxcc[1]->itu;
+ $org_cq = $dxcc[1]->cq;
+ }
+
+ # 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;
+
+ $dxchan->wcy($line, $self->{isolate}, @_, $self->{call}, $wcy_dxcc, $wcy_itu, $wcy_cq, $org_dxcc, $org_itu, $org_cq);
+ }
+}
+
+sub wcy
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{wcyfilter}) {
+ ($filter, $hops) = $self->{wcyfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line) if $self->is_clx || $self->is_spider || $self->is_dxnet;
+}
+
+# send an announce
+sub send_announce
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel->get_all();
+ my $dxchan;
+ my $target;
+ my $to = 'To ';
+ my $text = unpad($_[2]);
+
+ if ($_[3] eq '*') { # sysops
+ $target = "SYSOP";
+ } elsif ($_[3] gt ' ') { # speciality list handling
+ my ($name) = split /\./, $_[3];
+ $target = "$name"; # put the rest in later (if bothered)
+ }
+
+ if ($_[5] eq '1') {
+ $target = "WX";
+ $to = '';
+ }
+ $target = "ALL" if !$target;
+
+
+ # 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, $ann_state, $org_state);
+ unless ($filter) {
+ dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr');
+ return;
+ }
+ }
+
+ if (AnnTalk::dup($_[0], $_[1], $_[2])) {
+ dbg("PCPROT: Duplicate Announce ignored") if isdbg('chanerr');
+ return;
+ }
+
+ Log('ann', $target, $_[0], $text);
+
+ # 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;
+ $dxchan->announce($line, $self->{isolate}, $to, $target, $text, @_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
+ }
+}
+
+my $msgid = 0;
+
+sub nextchatmsgid
+{
+ $msgid++;
+ $msgid = 1 if $msgid > 999;
+ return $msgid;
+}
+
+# send a chat line
+sub send_chat
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel->get_all();
+ 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) = ("", "");
+ 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, $ann_state, $org_state);
+ unless ($filter) {
+ dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr');
+ return;