X-Git-Url: http://dxcluster.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FQXProt.pm;h=b9cf952cb497a553d4fed6aa0069f09d7d20e2f5;hb=ab10b5e76b152d41273281b30b019e4c82ed22d8;hp=bce0b56770f8daa5401401e8aa8f73a9f323fc23;hpb=50f6466ca2dff82ca470a4abe327d741cffef61a;p=spider.git diff --git a/perl/QXProt.pm b/perl/QXProt.pm index bce0b567..b9cf952c 100644 --- a/perl/QXProt.pm +++ b/perl/QXProt.pm @@ -29,20 +29,33 @@ use Route; use Route::Node; use Script; use DXProt; +use Verify; 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; +$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0)); $main::build += $VERSION; $main::branch += $BRANCH; -use vars qw($last_node_update $node_update_interval); - -$node_update_interval = 14*60; -$last_node_update = time; - +sub init +{ + my $user = DXUser->get($main::mycall); + $DXProt::myprot_version += $main::version*100; + $main::me = QXProt->new($main::mycall, 0, $user); + $main::me->{here} = 1; + $main::me->{state} = "indifferent"; + $main::me->{sort} = 'S'; # S for spider + $main::me->{priv} = 9; + $main::me->{metric} = 0; + $main::me->{pingave} = 0; + $main::me->{registered} = 1; + $main::me->{version} = $main::version; + $main::me->{build} = $main::build; + +# $Route::Node::me->adddxchan($main::me); +} sub start { @@ -50,31 +63,62 @@ sub start $self->SUPER::start(@_); } +sub sendinit +{ + my $self = shift; + + $self->send($self->genI); +} + sub normal { if ($_[1] =~ /^PC\d\d\^/) { DXProt::normal(@_); return; } - my $pcno; - return unless ($pcno) = $_[1] =~ /^QX(\d\d)\^/; + my ($sort, $tonode, $fromnode, $msgid, $incs); + return unless ($sort, $tonode, $fromnode, $msgid, $incs) = $_[1] =~ /^QX([A-Z])\^(\*|[-A-Z0-9]+)\^([-A-Z0-9]+)\^([0-9A-F]{1,4})\^.*\^([0-9A-F]{2})$/; - my ($self, $line) = @_; - - # calc checksum - $line =~ s/\^(\d\d)$//; - my $incs = hex $1; - my $cs = unpack("%32C*", $line) % 255; - if ($incs != $cs) { - dbg("QXPROT: Checksum fail in: $incs ne calc: $cs" ) if isdbg('qxerr'); + $msgid = hex $msgid; + my $noderef = Route::Node::get($fromnode); + $noderef = Route::Node::new($fromnode) unless $noderef; + + my $il = length $incs; + my $cs = sprintf("%02X", unpack("%32C*", substr($_[1], 0, length($_[1]) - ($il+1))) & 255); + if ($incs ne $cs) { + dbg("QXPROT: Checksum fail in: $incs ne calc: $cs" ) if isdbg('chanerr'); return; } - # split the field for further processing - my ($id, $tonode, $fromnode, @field) = split /\^/, $line; - + return unless $noderef->newid($msgid); + + $_[0]->handle($sort, $tonode, $fromnode, $msgid, $_[1]); + return; } +sub handle +{ + no strict 'subs'; + my $self = shift; + my $sort = shift; + my $sub = "handle$sort"; + $self->$sub(@_) if $self->can($sub); + return; +} + +sub gen +{ + no strict 'subs'; + my $self = shift; + my $sort = shift; + my $sub = "gen$sort"; + $self->$sub(@_) if $self->can($sub); + return; +} + +my $last_node_update = 0; +my $node_update_interval = 60*15; + sub process { if ($main::systime >= $last_node_update+$node_update_interval) { @@ -84,33 +128,119 @@ sub process } } -sub sendallnodes +sub disconnect +{ + my $self = shift; + $self->DXProt::disconnect(@_); +} + +my $msgid = 1; + +sub frame +{ + my $sort = shift; + my $to = shift || "*"; + my $ht; + + $ht = sprintf "%X", $msgid; + my $line = join '^', "QX$sort", $to, $main::mycall, $ht, @_; + my $cs = sprintf "%02X", unpack("%32C*", $line) & 255; + $msgid = 1 if ++$msgid > 0xffff; + return "$line^$cs"; +} + +sub handleI +{ + my $self = shift; + + my @f = split /\^/, $_[3]; + if ($self->passphrase && $f[7] && $f[8]) { + my $inv = Verify->new($f[7]); + unless ($inv->verify($f[8], $main::me->user->passphrase, $main::mycall, $self->call)) { + $self->sendnow('D','Sorry...'); + $self->disconnect; + } + $self->{verified} = 1; + } else { + $self->{verified} = 0; + } + if ($self->{outbound}) { + $self->send($self->genI); + } + if ($self->{sort} ne 'S' && $f[4] eq 'DXSpider') { + $self->{user}->{sort} = $self->{sort} = 'S'; + $self->{user}->{priv} = $self->{priv} = 1 unless $self->{priv}; + } + $self->{version} = $f[5]; + $self->{build} = $f[6]; + $self->state('init1'); + $self->{lastping} = 0; +} + +sub genI { - my $nodes = join(',', map {sprintf("%s:%d", $_->{call}, int($_->{pingave} * $_->{metric}))} DXChannel::get_all_nodes()); - my $users = DXChannel::get_all_users(); - DXChannel::broadcast_nodes(frame(2, undef, undef, hextime(), $users, 'S', $nodes)) + my $self = shift; + my @out = ('I', $self->call, "DXSpider", ($main::version + 53) * 100, $main::build); + if (my $pass = $self->user->passphrase) { + my $inp = Verify->new; + push @out, $inp->challenge, $inp->response($pass, $self->call, $main::mycall); + } + return frame(@out); } -sub sendallusers +sub handleR { } -sub hextime +sub genR { - my $t = shift || $main::systime; - return sprintf "%X", $t; + } -sub frame +sub handleP { - my $pcno = shift; - my $to = shift || ''; - my $from = shift || $main::mycall; + +} + +sub genP +{ + +} + +sub gen2 +{ + my $self = shift; + + my $node = shift; + my $sort = shift; + my @out; + my $dxchan; - my $line = join '^', sprintf("QX%02d", $pcno), $to, $from, @_; - my $cs = unpack("%32C*", $line) % 255; - return $line . sprintf("^%02X", $cs); + while (@_) { + my $str = ''; + for (; @_ && length $str <= 230;) { + my $ref = shift; + my $call = $ref->call; + my $flag = 0; + + $flag += 1 if $ref->here; + $flag += 2 if $ref->conf; + if ($ref->is_node) { + my $ping = int($ref->pingave * 10); + $str .= "^N$flag$call,$ping"; + my $v = $ref->build || $ref->version; + $str .= ",$v" if defined $v; + } else { + $str .= "^U$flag$call"; + } + } + push @out, $str if $str; + } + my $n = @out; + my $h = get_hops(90); + @out = map { sprintf "PC90^%s^%X^%s%d%s^%s^", $node->call, $main::systime, $sort, --$n, $_, $h } @out; + return @out; } 1;