+29Oct00=======================================================================
+1. put in echo cancelling measures into the clients. This doesn't mean you
+shouldn't take steps to prevent echoing on node links, but it may help where
+(whatever you do) it still bloody echos! This is experimental.
28Oct00=======================================================================
1. updated show/sun and show/moon from stuff sent by Steve Franke K9AN
2. added show/call which queries jeifer.pineknot.com for any call in the
world (as opposed to UALR which only does US calls). Inspired by a bit of
perl sent to me by Steve Franke (again!) and also Angel EA7WA who gave me the
pineknot ip address.
+3. fixed clients so that they accept -0 as a valid SSID and then strip it off
+as though they had come in without (why has this taken so long to appear? How
+long have we been running this code ??????).
27Oct00=======================================================================
1. alter the code in clean_old of DXMsg system to see if we get some different
behaviour with random crashing
return (1, $self->msg('e5')) if $who ne $self->call;
}
-@out = DXLog::print($from, $to, $main::systime, undef, $who);
+@out = DXLog::print($from, $to, $main::systime, $who);
return (1, @out);
my $count;
$search = '1' unless $pattern || $who;
- $search = "\$ref->[1] =~ /$pattern/" if $pattern;
+ $search = "\$ref->[1] =~ /$pattern/i" if $pattern;
$search .= ' && ' if $pattern && $who;
- $search .= "(\$ref->[2] =~ /$who/ || \$ref->[3] =~ /$who/)" if $who;
+ $search .= "(\$ref->[2] =~ /$who/i || \$ref->[3] =~ /$who/i)" if $who;
$eval = qq(
my \$c;
my \$ref;
$org_itu = $dxcc[1]->itu;
$org_cq = $dxcc[1]->cq();
}
- my ($filter, $hops) = Filter::it($self->{inannfilter}, @field[1..6], $self->{call},
+ my ($filter, $hops) = $self->{inannfilter}->it(@field[1..6], $self->{call},
$ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
unless ($filter) {
dbg('chan', "Rejected by filter");
my ($filter, $hops);
if ($dxchan->{spotfilter}) {
- ($filter, $hops) = Filter::it($dxchan->{spotfilter}, @_, $self->{call} );
+ ($filter, $hops) = $dxchan->{spotfilter}->it(@_, $self->{call} );
next unless $filter;
}
my ($filter, $hops);
if ($dxchan->{wwvfilter}) {
- ($filter, $hops) = Filter::it($dxchan->{wwvfilter}, @_, $self->{call} );
+ ($filter, $hops) = $dxchan->{wwvfilter}->it(@_, $self->{call} );
next unless $filter;
}
if ($dxchan->is_node) {
my ($filter, $hops);
if ($dxchan->{wcyfilter}) {
- ($filter, $hops) = Filter::it($dxchan->{wcyfilter}, @_, $self->{call} );
+ ($filter, $hops) = $dxchan->{wcyfilter}->it(@_, $self->{call} );
next unless $filter;
}
if ($dxchan->is_clx || $dxchan->is_spider) {
$org_itu = $dxcc[1]->itu;
$org_cq = $dxcc[1]->cq;
}
- ($filter, $hops) = Filter::it($dxchan->{annfilter}, @_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
+ ($filter, $hops) = $dxchan->{annfilter}->it(@_, $self->{call}, $ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq);
next unless $filter;
}
if ($dxchan->is_node && $_[1] ne $main::mycall) { # i.e not specifically routed to me
if ($sort eq 'dx') {
next unless $dxchan->{dx};
- ($filter) = Filter::it($dxchan->{spotfilter}, @{$fref}) if ref $fref;
+ ($filter) = $dxchan->{spotfilter}->it(@{$fref}) if ref $fref;
next unless $filter;
}
next if $sort eq 'ann' && !$dxchan->{ann};
#
# $Id$
#
-# The INSTRUCTIONS
+# The NEW INSTRUCTIONS
+#
+# use the commands accept/spot|ann|wwv|wcy and reject/spot|ann|wwv|wcy
+# also show/filter spot|ann|wwv|wcy
#
# The filters live in a directory tree of their own in $main::root/filter
#
# Each type of filter (e.g. spot, wwv) live in a tree of their own so you
# can have different filters for different things for the same callsign.
#
-# Each filter file has the same structure:-
-#
-# <some comment>
-# @in = (
-# [ action, fieldno, fieldsort, comparison, action data ],
-# ...
-# );
-#
-# The action is usually 1 or 0 but could be any numeric value
-#
-# The fieldno is the field no in the list of fields that is presented
-# to 'Filter::it'
-#
-# The fieldsort is the type of field that we are dealing with which
-# currently can be 'a', 'n', 'r' or 'd'. 'a' is alphanumeric, 'n' is
-# numeric, 'r' is ranges of pairs of numeric values and 'd' is default.
-#
-# Filter::it basically goes thru the list of comparisons from top to
-# bottom and when one matches it will return the action and the action data as a list.
-# The fields
-# are the element nos of the list that is presented to Filter::it. Element
-# 0 is the first field of the list.
-#
+
package Filter;
use DXVars;
use DXUtil;
use DXDebug;
+use Data::Dumper;
use strict;
}
-#
-# takes the reference to the filter (the first argument) and applies
-# it to the subsequent arguments and returns the action specified.
-#
-sub it
-{
- my $filter = shift;
- my ($action, $field, $fieldsort, $comp, $actiondata);
- my $ref;
-
- # default action is 1
- $action = 1;
- $actiondata = "";
- return ($action, $actiondata) if !$filter;
-
- for $ref (@{$filter}) {
- ($action, $field, $fieldsort, $comp, $actiondata) = @{$ref};
- if ($fieldsort eq 'n') {
- my $val = $_[$field];
- return ($action, $actiondata) if grep $_ == $val, @{$comp};
- } elsif ($fieldsort eq 'r') {
- my $val = $_[$field];
- my $i;
- my @range = @{$comp};
- for ($i = 0; $i < @range; $i += 2) {
- return ($action, $actiondata) if $val >= $range[$i] && $val <= $range[$i+1];
- }
- } elsif ($fieldsort eq 'a') {
- return ($action, $actiondata) if $_[$field] =~ m{$comp};
- } else {
- return ($action, $actiondata); # the default action
- }
- }
-}
# this reads in a filter statement and returns it as a list
#
# load it
if (-e $fn) {
- do "$fn";
+ $in = undef;
+ my $s = readfilestr($fn);
+ my $newin = eval $s;
dbg('conn', "$@") if $@;
- return $in;
+ return bless [ @$in ], 'Filter::Old' if $in;
+ return $newin;
}
return undef;
}
# this writes out the filter in a form suitable to be read in by 'read_in'
# It expects a list of references to filter lines
-sub write_out
+sub write
{
+ my $self = shift;
+
my $sort = shift;
my $call = shift;
my $fn = "$filterbasefn/$sort";
close FILTER;
}
+package Filter::Old;
+
+use strict;
+use vars qw(@ISA);
+@ISA = qw(Filter);
+
+# the OLD instructions!
+#
+# Each filter file has the same structure:-
+#
+# <some comment>
+# @in = (
+# [ action, fieldno, fieldsort, comparison, action data ],
+# ...
+# );
+#
+# The action is usually 1 or 0 but could be any numeric value
+#
+# The fieldno is the field no in the list of fields that is presented
+# to 'Filter::it'
+#
+# The fieldsort is the type of field that we are dealing with which
+# currently can be 'a', 'n', 'r' or 'd'. 'a' is alphanumeric, 'n' is
+# numeric, 'r' is ranges of pairs of numeric values and 'd' is default.
+#
+# Filter::it basically goes thru the list of comparisons from top to
+# bottom and when one matches it will return the action and the action data as a list.
+# The fields
+# are the element nos of the list that is presented to Filter::it. Element
+# 0 is the first field of the list.
+#
+
+#
+# takes the reference to the filter (the first argument) and applies
+# it to the subsequent arguments and returns the action specified.
+#
+sub it
+{
+ my $filter = shift; # this is now a bless ref of course but so what
+
+ my ($action, $field, $fieldsort, $comp, $actiondata);
+ my $ref;
+
+ # default action is 1
+ $action = 1;
+ $actiondata = "";
+ return ($action, $actiondata) if !$filter;
+
+ for $ref (@{$filter}) {
+ ($action, $field, $fieldsort, $comp, $actiondata) = @{$ref};
+ if ($fieldsort eq 'n') {
+ my $val = $_[$field];
+ return ($action, $actiondata) if grep $_ == $val, @{$comp};
+ } elsif ($fieldsort eq 'r') {
+ my $val = $_[$field];
+ my $i;
+ my @range = @{$comp};
+ for ($i = 0; $i < @range; $i += 2) {
+ return ($action, $actiondata) if $val >= $range[$i] && $val <= $range[$i+1];
+ }
+ } elsif ($fieldsort eq 'a') {
+ return ($action, $actiondata) if $_[$field] =~ m{$comp};
+ } else {
+ return ($action, $actiondata); # the default action
+ }
+ }
+}
+
+
1;
__END__
if ($buffered) {
if (length $outqueue >= $client_buffer_lth) {
print $stdout $outqueue;
+ pop @echo if @echo > $maxecho;
+ push @echo, $outqueue;
$outqueue = "";
}
$outqueue .= "$savenl$line$snl";
} elsif ($sort eq 'B') {
if ($buffered && $outqueue) {
print $stdout $outqueue;
+ pop @echo if @echo > $maxecho;
+ push @echo, $outqueue;
$outqueue = "";
}
$buffered = $line; # set buffered or unbuffered
unshift @lines, ($lastbit . $first) if ($first);
foreach $first (@lines) {
# print "send_now $call $first\n";
+ next if grep {$_ eq $first } @echo;
$conn->send_later("I$call|$first");
}
$lastbit = $buf;
$timeout = 60; # default timeout for connects
$abort = ""; # the current abort string
$cpath = "$root/connect"; # the basic connect directory
+$maxecho = 5; # length of max echo queue
$pid = 0; # the pid of the child program
$csort = ""; # the connection type
#include "sel.h"
#include "cmsg.h"
+#include "chain.h"
#include "debug.h"
#define TEXT 1
char *connsort = "local"; /* the connection variety */
int state = 0; /* the current state of the connection */
int laststate = 0; /* the last state we were in */
-
-
+reft echobase; /* the anti echo queue */
+int maxecho = 5; /* the depth of the anti echo queue */
+int echon; /* no of entries in the anti echo queue */
#define CONNECTED 100
#define WAITLOGIN 1
void flush_text(fcb_t *f)
{
if (f->obuf) {
- cmsg_send(f->outq, f->obuf, 0);
+ /* save this onto the front of the echo chain */
+ cmsg_t *imp = f->obuf;
+ int size = imp->inp - imp->data;
+ cmsg_t *emp = cmsg_new(size, imp->sort, imp->portp);
+
+ emp->size = size;
+ memcpy(emp->data, imp->data, size);
+ emp->inp = emp->data + size; /* just in case */
+ chain_add(&echobase, emp);
+ if (++echon > maxecho) {
+ emp = cmsg_prev(&echobase);
+ cmsg_free(emp);
+ }
+
+ /* queue it for sending */
+ cmsg_send(f->outq, imp, 0);
f->sp->flags |= SEL_OUTPUT;
f->obuf = 0;
}
void process_stdin()
{
- cmsg_t *mp = cmsg_next(in->inq);
+ cmsg_t *wmp, *mp = cmsg_next(in->inq);
char *p, hasa, hasn, i;
char callsign[MAXCALLSIGN+1];
if (mp) {
dbg(DMSG, "MSG size: %d", mp->size);
+
+ /* check for echos */
+ for (wmp = 0; wmp = chain_get_next(&echobase, wmp); ) {
+ if (!memcmp(wmp->data, mp->data, wmp->size)) {
+ cmsg_callback(mp, 0);
+ return;
+ }
+ }
switch (state) {
case CONNECTED:
#ifdef SIGPWR
signal(SIGPWR, terminate);
#endif
+ /* init a few things */
+ chain_init(&echobase);
/* connect up stdin */
in = fcb_new(0, TEXT);
return mp;
}
+
void cmsg_send(reft *base, cmsg_t *mp, void (*callback)())
{
time(&mp->t);
/*
*
* $Log$
- * Revision 1.2 2000-07-20 14:16:00 minima
+ * Revision 1.3 2000-10-29 11:00:07 minima
+ * added echo cancelling
+ * started new filter code, objectifyed old filter code
+ *
+ * Revision 1.2 2000/07/20 14:16:00 minima
* can use Sourceforge now!
* added user->qra cleaning
* added 4 digit qra to user broadcast dxspots if available