@ISA = qw(DXChannel);
+require 5.10.1;
+
use POSIX qw(:math_h);
use DXUtil;
use DXChannel;
use VE7CC;
use DXXml;
use AsyncMsg;
+use JSON;
+use Time::HiRes qw(gettimeofday tv_interval);
+
+use Mojo::IOLoop;
+use Mojo::IOLoop::ForkCall;
+use Mojo::UserAgent;
use strict;
use vars qw(%Cache %cmd_cache $errstr %aliases $scriptbase %nothereslug
my $pkg = shift;
my $call = shift;
# my @rout = $main::routeroot->add_user($call, Route::here(1));
- DXProt::_add_thingy($main::routeroot, [$call, 0, 0, 1, undef, undef, $self->{conn}->peerhost], );
+ DXProt::_add_thingy($main::routeroot, [$call, 0, 0, 1, undef, undef, $self->hostname], );
# ALWAYS output the user
my $ref = Route::User::get($call);
my $host = $self->{conn}->peerhost;
$host ||= "AGW Port #$self->{conn}->{agwport}" if exists $self->{conn}->{agwport};
$host ||= "unknown";
- LogDbg('DXCommand', "$call connected from $host");
+ $self->{hostname} = $host;
$self->{name} = $name ? $name : $call;
$self->send($self->msg('l2',$self->{name}));
$pagelth = $default_pagelth unless defined $pagelth;
$self->{pagelth} = $pagelth;
($self->{width}) = $line =~ /width=(\d+)/; $line =~ s/\s*width=\d+\s*//;
+ if ($line =~ /host=/) {
+ my ($h) = $line =~ /host=(\d+\.\d+\.\d+\.\d+)/;
+ $line =~ s/\s*host=\d+\.\d+\.\d+\.\d+// if $h;
+ unless ($h) {
+ ($h) = $line =~ /host=([\da..fA..F:]+)/;
+ $line =~ s/\s*host=[\da..fA..F:]+// if $h;
+ }
+ $self->{hostname} = $h if $h;
+ }
$self->{width} = 80 unless $self->{width} && $self->{width} > 80;
$self->{consort} = $line; # save the connection type
-
+
+ LogDbg('DXCommand', "$call connected from $self->{hostname}");
+
# set some necessary flags on the user if they are connecting
$self->{beep} = $user->wantbeep;
$self->{ann} = $user->wantann;
$self->{ann_talk} = $user->wantann_talk;
$self->{here} = 1;
$self->{prompt} = $user->prompt if $user->prompt;
+ $self->{lastmsgpoll} = 0;
# sort out new dx spot stuff
$user->wantdxcq(0) unless defined $user->{wantdxcq};
$self->send_motd;
# sort out privilege reduction
- $self->{priv} = 0 if $line =~ /^(ax|te)/ && !$self->conn->{usedpasswd};
+ $self->{priv} = 0 unless $self->{hostname} eq '127.0.0.1' || $self->{hostname} eq '::1' || $self->conn->{usedpasswd};
# get the filters
my $nossid = $call;
my $dxchan;
foreach $dxchan (@dxchan) {
- next if $dxchan->sort ne 'U';
+ next unless $dxchan->is_user;
# send a outstanding message prompt if required
if ($t >= $dxchan->lastmsgpoll + $msgpolltime) {
my $s = shift; # the line to be rebroadcast
foreach my $dxchan (DXChannel::get_all()) {
- next unless $dxchan->{sort} eq 'U'; # only interested in user channels
+ next unless $dxchan->is_user; # only interested in user channels
next if grep $dxchan == $_, @_;
$dxchan->send($s); # send it
}
# gimme all the users
sub get_all
{
- return grep {$_->{sort} eq 'U'} DXChannel::get_all();
+ return grep {$_->is_user} DXChannel::get_all();
}
# run a script for this user
{
my $s = shift; # the line to be rebroadcast
- foreach my $dxchan (DXChannel::get_all) {
+ foreach my $dxchan (DXChannel::get_all_users) {
next unless $dxchan->{enhanced} && $dxchan->{senddbg};
if ($dxchan->{gtk}) {
$dxchan->send_later('L', dd(['db', $s]));
my @names = readdir(DIR);
closedir(DIR);
my $name;
+
+ return unless @names;
+
foreach $name (@names) {
next if $name =~ /^\./;
}
$self->send_file($motd) if -e $motd;
}
+
+sub _diffms
+{
+ return unless isdbg('chan');
+ my $call = shift;
+ my $line = shift;
+ my $ta = shift;
+ my $tb = shift || [gettimeofday];
+
+ my $a = int($ta->[0] * 1000) + int($ta->[1] / 1000);
+ my $b = int($tb->[0] * 1000) + int($tb->[1] / 1000);
+ my $msecs = $b - $a;
+
+ my $s = "forkcall stats: $call '$line' ";
+ $s .= "${msecs}mS";
+ dbg($s);
+}
+
+# Punt off a long running command into a separate process
+#
+# This is called from commands to run some potentially long running
+# function. The process forks and then runs the function and returns
+# the result back to the cmd.
+#
+# NOTE: this merely forks the current process and then runs the cmd in that (current) context.
+# IT DOES NOT START UP SOME NEW PROGRAM AND RELIES ON THE FACT THAT IT IS RUNNING DXSPIDER
+# THE CURRENT CONTEXT!!
+#
+# call: $self->spawn_cmd($original_cmd_line, \<function>, [cb => sub{...}], [prefix => "cmd> "], [progress => 0|1], [args => [...]]);
+sub spawn_cmd
+{
+ my $self = shift;
+ my $line = shift;
+ my $cmdref = shift;
+ my $call = $self->{call};
+ my %args = @_;
+ my @out;
+
+ my $cb = delete $args{cb};
+ my $prefix = delete $args{prefix};
+ my $progress = delete $args{progress};
+ my $args = delete $args{args} || [];
+ my $t0 = [gettimeofday];
+
+ no strict 'refs';
+
+ my $fc = Mojo::IOLoop::ForkCall->new;
+ $fc->serializer(\&encode_json);
+ $fc->deserializer(\&decode_json);
+ $fc->run(
+ sub {my @args = @_; my @res = $cmdref->(@args); return @res},
+ $args,
+ sub {
+ my ($fc, $err, @res) = @_;
+ my $dxchan = DXChannel::get($call);
+ return unless $dxchan;
+
+ if (defined $err) {
+ my $s = "DXCommand::spawn_cmd: call $call error $err";
+ dbg($s) if isdbg('chan');
+ $dxchan->send($s);
+ return;
+ }
+ if ($cb) {
+ $cb->($dxchan, @res);
+ } else {
+ return unless @res;
+ if (defined $prefix) {
+ $dxchan->send(map {"$prefix$_"} @res);
+ } else {
+ $dxchan->send(@res);
+ }
+ }
+ _diffms($call, $line, $t0);
+ });
+
+ return @out;
+}
+
1;
__END__