Add and process IP addresses on PC93.
Remove uninitialised messages.
Add LOCALE=(UTC|LOCAL) time operation to crontab.
Make PC92 A/D processing and distribution optional.
Add a switch to PC92 C to add IP addresses optional.
+30Jan23=======================================================================
+1. Add ip addresses to outgoing PC93 messages
+2. Get rid of (some of?) the uninitialised warnings
+3. Add the ability to set the (time) locale to UTC or LOCALTIME by adding
+ the string LOCALE = UTC or LOCALE = LOCAL(TIME)? to your local crontab
+
+ NOTE: this will affect ALL timings in both the system as well as your
+ local crontabs. Changing the LOCALE will make no difference to the system
+ crontab other than using localtime rather than UTC. Which is fine by me.
+
+ You can see what crontab is doing and which LOCALE is in use by doing a
+ 'set/debug cron' in a console and running a 'watchdbg cron' in another
+ shell.
+25Jan23=======================================================================
+1. Add a switch to enable the routing of generated PC92 A/D records and also
+ prevent the rebroadcast of incoming ones.
+
+ set/var $DXProt::pc92_ad_enable 0
+
+ to disable PC92 A/D records.
+2. Add a switch to enable the addition of IP addresses to PC92 C records.
+
+ set/var $DXProt::pc92c_ipaddr_enable 1
+
+ to enable the addition of IP addresses to outgoing PC92 C records.
+
+ ## These two features are experimental, but will become the default if
+ ## some other changes and these are successful
24Jan23=======================================================================
1. Optimise the PC11->PC61 promotion code, improve readability of the
debugging when 'set/debug pc11' is active.
}
#return (1, $self->msg('dup')) if $self->priv < 5 && AnnTalk::dup($from, $toflag, $line);
+my $ipaddr = DXCommandmode::alias_localhost($self->hostname || '127.0.0.1');
Log('ann', $to, $from, $line);
-$main::me->normal(DXProt::pc93($to, $from, $via, $line));
+$main::me->normal(DXProt::pc93($to, $from, $via, $line, undef, $ipaddr));
#DXChannel::broadcast_list("To $to de $from ($t): $line\a", 'ann', undef, @locals);
#if ($to ne "LOCAL") {
# default the 'via'
#$via ||= '*';
+my $ipaddr = DXCommandmode::alias_localhost($self->hostname || '127.0.0.1');
+
# if there is a line send it, otherwise add this call to the talk list
# and set talk mode for command mode
if ($line) {
$self->badcount(($self->badcount||0) + @bad);
LogDbg('DXCommand', "$self->{call} swore: $line (with words:" . join(',', @bad) . ")");
} else {
- $main::me->normal(DXProt::pc93($to, $self->call, $via, $line));
+ $main::me->normal(DXProt::pc93($to, $self->call, $via, $line, undef, $ipaddr));
}
} else {
my $s = $to;
my $ref = $self->talklist;
if ($ref) {
unless (grep { $_ eq $s } @$ref) {
- $main::me->normal(DXProt::pc93($to, $self->call, $via, $self->msg('talkstart')));
+ $main::me->normal(DXProt::pc93($to, $self->call, $via, $self->msg('talkstart'), undef, $ipaddr));
$self->state('talk');
push @$ref, $s;
}
} else {
$self->talklist([ $s ]);
- $main::me->normal(DXProt::pc93($to, $self->call, $via, $self->msg('talkstart')));
+ $main::me->normal(DXProt::pc93($to, $self->call, $via, $self->msg('talkstart'), undef, $ipaddr));
push @out, $self->msg('talkinst');
$self->state('talk');
}
- Log('talk', $to, $from, '>' . ($via || ($dxchan && $dxchan->call) || '*'), $self->msg('talkstart'));
+ Log('talk', $to, $from, '>' . ($via || ($dxchan && $dxchan->call) || '*'), $self->msg('talkstart'), undef, $ipaddr);
push @out, $self->talk_prompt;
}
return (1, ());
}
-Log('ann', $via ? $via : '*', $from, $line);
-$main::me->normal(DXProt::pc93($to, $from, $via, $line));
+my $ipaddr = DXCommandmode::alias_localhost($self->hostname || '127.0.0.1');
+
+Log('ann', $via ? $via : '*', $from, $line, $ipaddr);
+$main::me->normal(DXProt::pc93($to, $from, $via, $line, undef, $ipaddr));
#DXChannel::broadcast_list("WX de $from <$t>: $line", 'wx', undef, @locals);
#if ($to ne "LOCAL") {
chomp;
next if /^\s*\#/;
next unless /[\.:]/;
+ next unless $_;
push @out, $_;
}
$fh->close;
my $ipaddr = alias_localhost($self->hostname);
DXProt::_add_thingy($main::routeroot, [$call, 0, 0, 1, undef, undef, $ipaddr], );
- # ALWAYS output the user
+ # ALWAYS output the user (except if the updates not enabled)
my $ref = Route::User::get($call);
if ($ref) {
$main::me->route_pc16($main::mycall, undef, $main::routeroot, $ref);
- $main::me->route_pc92a($main::mycall, undef, $main::routeroot, $ref) unless $DXProt::pc92_slug_changes;
+ $main::me->route_pc92a($main::mycall, undef, $main::routeroot, $ref) unless $DXProt::pc92_slug_changes || ! $DXProt::pc92_ad_enable;
}
return $self;
my $msgid = DXProt::nextchatmsgid();
$text = "#$msgid $text";
- $main::me->normal(DXProt::pc93($target, $self->{call}, undef, $text));
+ my $ipaddr = alias_localhost($self->hostname || '127.0.0.1');
+ $main::me->normal(DXProt::pc93($target, $self->{call}, undef, $text, undef, $ipaddr));
}
sub special_prompt
# issue a pc17 to everybody interested
$main::me->route_pc17($main::mycall, undef, $main::routeroot, $uref);
- $main::me->route_pc92d($main::mycall, undef, $main::routeroot, $uref) unless $DXProt::pc92_slug_changes;
+ $main::me->route_pc92d($main::mycall, undef, $main::routeroot, $uref) unless $DXProt::pc92_slug_changes || ! $DXProt::pc92_ad_enable;
} else {
confess "trying to disconnect a non existant user $call";
}
use strict;
-use vars qw{@crontab @lcrontab @scrontab $mtime $lasttime $lastmin};
+use vars qw{@crontab @lcrontab @scrontab $mtime $lasttime $lastmin $use_localtime};
$mtime = 0;
$lasttime = 0;
$lastmin = 0;
-
+$use_localtime = 0;
my $fn = "$main::cmd/crontab";
my $localfn = "$main::localcmd/crontab";
while (my $l = <$fh>) {
$line++;
chomp $l;
- next if $l =~ /^\s*#/o or $l =~ /^\s*$/o;
+ next if $l =~ /^\s*#/ or $l =~ /^\s*$/;
+ if (my ($ts) = $l =~/^\s*LOCALE\s*=\s*(UTC|LOCAL)/i) {
+ $ts = uc $ts;
+ if ($ts eq 'UTC') {
+ $use_localtime = 0;
+ } elsif ($ts eq 'LOCAL') {
+ $use_localtime = 1;
+ }
+ dbg("DXCron: LOCALE set to $ts") if isdbg('cron');
+ }
my ($min, $hour, $mday, $month, $wday, $cmd) = $l =~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)$/;
next unless defined $min;
my $ref = bless {};
my $now = $main::systime;
return if $now-$lasttime < 1;
- my ($sec, $min, $hour, $mday, $mon, $wday) = (gmtime($now))[0,1,2,3,4,6];
+ my ($sec, $min, $hour, $mday, $mon, $wday);
+ if ($use_localtime) {
+ ($sec, $min, $hour, $mday, $mon, $wday) = (localtime($now))[0,1,2,3,4,6];
+ } else {
+ ($sec, $min, $hour, $mday, $mon, $wday) = (gmtime($now))[0,1,2,3,4,6];
+ }
# are we at a minute boundary?
if ($min != $lastmin) {
(!$cron->{wday} || grep $_ eq $wday, @{$cron->{wday}}) ){
if ($cron->{cmd}) {
- dbg("cron: $min $hour $mday $mon $wday -> doing '$cron->{cmd}'") if isdbg('cron');
+ my $s = $use_localtime ? "LOCALTIME" : "UTC";
+ dbg("cron: $s $min $hour $mday $mon $wday -> doing '$cron->{cmd}'") if isdbg('cron');
eval $cron->{cmd};
dbg("cron: cmd error $@") if $@ && isdbg('cron');
}
sub find
{
+ return 0 unless $_[0];
return $d{$_[0]};
}
{
my $s = shift;
my $t = shift || $main::systime + $default;
+ return unless $s;
+
$d{$s} = $t;
- dbg(sprintf("DXDupe::add key: $s time: %s", ztime($t))) if isdbg('dxdupe');
+ dbg("DXDupe::add key: $s time: " . ztime($t)) if isdbg('dxdupe');
}
sub del
{
my $s = shift;
- dbg(sprintf("DXDupe::del key: $s time: %s", ztime($d{$s}))) if isdbg('dxdupe');
+ return unless $s;
+
+ my $t = $d{$s};
+ dbg("DXDupe::del key: $s time: " . ztime($t)) if isdbg('dxdupe');
delete $d{$s};
}
%pc92_find $pc92_find_timeout $pc92_short_update_period
$next_pc92_obs_timeout $pc92_slug_changes $last_pc92_slug
$pc92_extnode_update_period $pc50_interval
- $pc92_keepalive_period $senderverify
+ $pc92_keepalive_period $senderverify $pc92_ad_enabled
+ $pc92c_ipaddr_enable
);
$pc11_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc11
%pc92_find = (); # outstanding pc92 find operations
$pc92_find_timeout = 30; # maximum time to wait for a reply
$senderverify = 0; # 1 = check spotter is on node it says it is and check ip address if available
- # 2 = do 1 and dump if check
-
+; # 2 = do 1 and dump if check
+$pc92_ad_enabled = 1; # send pc92 A & D records.
+$pc92c_ipaddr_enable = 0; # add the local ip address info to each callsign in a PC92 C
@checklist =
(
{
my ($self, $from, $to, $via, $line, $origin) = @_;
+ my $ipaddr = DXCommandmode::alias_localhost($self->hostname || '127.0.0.1');
if ($self->{do_pc9x}) {
- $self->send(pc93($to, $from, $via, $line));
+ $self->send(pc93($to, $from, $via, $line, undef, $ipaddr));
} else {
$self->send(pc10($from, $to, $via, $line, $origin));
}
- Log('talk', $to, $from, '>' . ($via || $origin || $self->call), $line) unless $origin && $origin ne $main::mycall;
+ Log('talk', $to, $from, '>' . ($via || $origin || $self->call), $line, $ipaddr) unless $origin && $origin ne $main::mycall;
}
# send it if it isn't the except list and isn't isolated and still has a hop count
my $self = shift;
my $origin = shift;
my $line = shift;
+
broadcast_route_pc9x($self, $origin, \&pc92c, $line, 1, @_);
}
my $self = shift;
my $origin = shift;
my $line = shift;
+ return unless $pc92_ad_enabled;
broadcast_route_pc9x($self, $origin, \&pc92a, $line, 1, @_);
}
my $self = shift;
my $origin = shift;
my $line = shift;
+ return unless $pc92_ad_enabled;
broadcast_route_pc9x($self, $origin, \&pc92d, $line, 1, @_);
}
$via = '*' if $target eq 'ALL' || $target eq 'SYSOP';
Log('ann', $target, $main::mycall, $text);
AnnTalk::add_anncache('ann', $target, $main::mycall, $text);
-
- $main::me->normal(DXProt::pc93($target, $main::mycall, $via, $text));
+ my $ipaddr = DXCommandmode::alias_localhost($main::me->hostname || '127.0.0.1');
+ $main::me->normal(DXProt::pc93($target, $main::mycall, $via, $text, undef, $ipaddr));
} else {
DXCommandmode::send_chats($main::me, $target, $text);
}
$eph_pc15_restime $pc9x_past_age $pc9x_dupe_age
$pc10_dupe_age $pc92_slug_changes $last_pc92_slug
$pc92Ain $pc92Cin $pc92Din $pc92Kin $pc9x_time_tolerance
- $pc92filterdef $senderverify $pc11_dwell_time $pc11_extract_route
+ $pc92filterdef $senderverify $pc11_dwell_time $pc11_extract_route $pc92_ad_enabled $pc92c_ipaddr_enable
);
$pc9x_dupe_age = 60; # catch loops of circular (usually) D records
}
# convert this to a PC93, coming from mycall with origin set and process it as such
- $main::me->normal(pc93($to, $from, $via, $pc->[3], $pc->[6]));
+ my $ref = Route::get($pc->[6]);
+ my $ip = $ref->ip;
+ $main::me->normal(pc93($to, $from, $via, $pc->[3], $pc->[6]), $ip);
}
my %pc11_saved; # delayed PC11s
}
# Populate the routing table
- my $rn = Route::Node::get($pc->[7]);
- unless ($rn) {
- $rn = Route::Node->new($pc->[7]);
- dbg("ROUTE $self->{call}: ADD NEW node: $pc->[7]") if isdbg('pc11');
- }
+ $self->populate_routing_table($pc->[7], $pc->[6], $pc->[8]);
my $r = Route::User::get($pc->[6]);
- unless ($r) {
- $rn->add_user($pc->[6], 0, undef);
- dbg("ROUTE $self->{call}: ADD NEW user: $pc->[6] -> $pc->[7]") if isdbg('pc11');
- $r = Route::User::get($pc->[6]);
- }
-
- # Add/Change any IP address info
if ($pcno == 61) {
-
- # as we have a route to a user, if it (or the node) does not exist then create them
- # link the user to the node if not already done.
- # then add or alter the IP address
- if ($pc->[8]) {
- my $new = $pc->[8];
- if ($r) {
- if ($r->ip ne $new) {
- if ($r->ip) {
- my $old = $r->ip;
- $r->ip($new);
- dbg("ROUTE $self->{call}: ALTER IP node: $pc->[7] user: $pc->[6] old IP: '$old'-> new IP: '$new'") if isdbg('pc11');
- } else{
- $r->ip($new);
- dbg("ROUTE $self->{call}: NEW IP node: $pc->[7] user: $pc->[6] IP: '$new'") if isdbg('pc11');
- }
- }
- } else {
- dbg("ROUTE $self->{call}: ADD Failed for node $pc->[7] user $pc->[6]") if isdbg('pc11');
- }
- } else {
- dbg("PCPROT: ROUTE $self->{call} NO IP ADDRESS in '$line'!");
+ unless ($pc->[8] && is_ipaddr($pc->[8])) {
+ dbg("PCPROT: ROUTE $self->{call} NO IP ADDRESS in '$line'!");
}
}
}
# broadcast it if we get here
- $self->broadcast_route_pc9x($pcall, undef, $line, 0);
+ $self->broadcast_route_pc9x($pcall, undef, $line, 0) unless !$pc92_ad_enabled && ($sort eq 'A' || $sort eq 'D');
}
# get all the routes for a thing, bearing in mind that the thing (e.g. a user)
my $via = uc $pc->[5];
my $text = $pc->[6];
my $onode = uc $pc->[7];
- $onode = $pcall if @$pc <= 8;
+ my $ipaddr = $pc->[8];
+
+ $onode //= $pcall;
# this is catch loops caused by bad software ...
if (eph_dup("PC93|$from|$text|$onode", $pc10_dupe_age)) {
}
}
+ $self->populate_routing_table($onode, $from, $ipaddr);
+
# if it is routeable then then treat it like a talk
my $ref = Route::get($to);
if ($ref) {
}
}
+sub populate_routing_table
+{
+ my ($self, $node, $user, $ip) = @_;
+
+ my $rn = Route::Node::get($node);
+ unless ($rn) {
+ $rn = Route::Node->new($node);
+ dbg("ROUTE $self->{call}: ADD NEW node: $node") if isdbg('pc11');
+ }
+
+ my $ru;
+ if ($user ne $node) {
+ $ru = Route::User::get($user);
+ unless ($ru) {
+ $rn->add_user($user, 0, undef);
+ dbg("ROUTE $self->{call}: ADD NEW user: $user -> $node") if isdbg('pc11');
+ }
+ $ru = Route::User::get($user);
+ }
+
+ # Add/Change any IP address info
+
+ # as we have a route to a user, if it (or the node) does not exist then create them
+ # link the user to the node if not already done.
+ # then add or alter the IP address
+ if ($ip && is_ipaddr($ip)) {
+ my $new = $ip;
+ if ($ru) {
+ if ($ru->ip ne $new) {
+ if ($ru->ip) {
+ my $old = $ru->ip;
+ $ru->ip($new);
+ dbg("ROUTE $self->{call}: ALTER IP node: $node user: $user old IP: '$old'-> new IP: '$new'") if isdbg('pc11');
+ } else{
+ $ru->ip($new);
+ dbg("ROUTE $self->{call}: NEW IP node: $node user: $user IP: '$new'") if isdbg('pc11');
+ }
+ }
+ } else {
+ dbg("ROUTE $self->{call}: ADD Failed for node $node user $user") if isdbg('pc11');
+ }
+ }
+}
+
1;
use strict;
-use vars qw($sentencelth $pc19_version $pc9x_nodupe_first_slot);
+use vars qw($sentencelth $pc19_version $pc9x_nodupe_first_slot $pc92c_ipaddr_enable);
$sentencelth = 180;
$pc9x_nodupe_first_slot = 1;
}
for (@_) {
$s .= '^' . _encode_pc92_call($_, $ext);
- $ext = 0 unless $sort eq 'A'; # only the first slot has an ext.
+ $ext = 0 unless $sort eq 'A '; # only the first slot has an ext except A
+ $ext = 2 if $pc92c_ipaddr_enable && $sort eq 'C';
}
return $s . '^H99^';
}
# send a config
sub pc92c
{
- return _gen_pc92('C', 1, @_);
+ return _gen_pc92('C', $pc92c_ipaddr_enable ? 2 : 1, @_);
}
# send a keep alive
my $via = shift || '*'; # *, node call
my $line = shift; # the text
my $origin = shift; # this will be present on proxying from PC10
+ my $ipaddr = shift;
$line = unpad($line);
$line =~ s/\^/~/g; # remove any ^ characters
my $s = "PC93^$main::mycall^" . gen_pc9x_t() . "^$to^$from^$via^$line";
$s .= "^$origin" if $origin;
+ if ($ipaddr) {
+ $s .= ' ^' unless $origin;
+ $ipaddr =~ s/:/,/;
+ $s .= "^$ipaddr";
+ }
$s .= "^H99^";
return $s;
}
sub write_cache
{
my $json = DXJSON->new;
- $json->canonical(isdbg('routecache'));
+ $json->canonical(isdbg('routecache')||0);
my $ta = [ gettimeofday ];
my @s;
sub write_cache
{
my $json = DXJSON->new;
- $json->canonical(isdbg('routecache'));
+ $json->canonical(isdbg('routecache')||0);
my $ta = [ gettimeofday ];
my @s;
sub per_10_minute
{
RBN::per_10_minute();
- Route::write_cache();
+ Route::write_cache() if $save_route_cache;
}
sub per_hour