start work on NP stuff seriously
[spider.git] / perl / QXProt.pm
1 #
2 # This module impliments the new protocal mode for a dx cluster
3 #
4 # Copyright (c) 2001 Dirk Koopman G1TLH
5 #
6 # $Id$
7
8
9 package QXProt;
10
11 @ISA = qw(DXChannel DXProt);
12
13 use DXUtil;
14 use DXChannel;
15 use DXUser;
16 use DXM;
17 use DXLog;
18 use Spot;
19 use DXDebug;
20 use Filter;
21 use DXDb;
22 use AnnTalk;
23 use Geomag;
24 use WCY;
25 use Time::HiRes qw(gettimeofday tv_interval);
26 use BadWords;
27 use DXHash;
28 use Route;
29 use Route::Node;
30 use Script;
31 use DXProt;
32 use Verify;
33
34 use strict;
35
36 use vars qw($VERSION $BRANCH);
37 $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
38 $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ ) || 0;
39 $main::build += $VERSION;
40 $main::branch += $BRANCH;
41
42 sub init
43 {
44         my $user = DXUser->get($main::mycall);
45         $DXProt::myprot_version += $main::version*100;
46         $main::me = QXProt->new($main::mycall, 0, $user); 
47         $main::me->{here} = 1;
48         $main::me->{state} = "indifferent";
49         $main::me->{sort} = 'S';    # S for spider
50         $main::me->{priv} = 9;
51         $main::me->{metric} = 0;
52         $main::me->{pingave} = 0;
53         $main::me->{registered} = 1;
54         $main::me->{version} = $main::version;
55         $main::me->{build} = $main::build;
56                 
57 #       $Route::Node::me->adddxchan($main::me);
58 }
59
60 sub start
61 {
62         my $self = shift;
63         $self->SUPER::start(@_);
64 }
65
66 sub sendinit
67 {
68         my $self = shift;
69         
70         $self->send($self->gen1);
71 }
72
73 sub normal
74 {
75         if ($_[1] =~ /^PC\d\d\^/) {
76                 DXProt::normal(@_);
77                 return;
78         }
79         my ($id, $fromnode, $msgid, $incs);
80         return unless ($id, $fromnode, $msgid, $incs) = $_[1] =~ /^QX(\d\d)\^([-A-Z0-9]+)\^([0-9A-F]{1,4})\^.*\^([0-9A-F]{2})$/;
81
82         my $noderef = Route::Node::get($fromnode);
83         $noderef = Route::Node::new($fromnode) unless $noderef;
84         my $user = DXChannel->get_current($fromnode);
85
86         my $il = length $incs; 
87         my $cs = sprintf("%02X", unpack("%32C*", substr($_[1], 0, length($_[1]) - ($il+1))));
88         if ($incs ne $cs) {
89                 dbg("QXPROT: Checksum fail in: $incs ne calc: $cs" ) if isdbg('chanerr');
90                 return;
91         }
92
93         return unless $noderef->newid($msgid);
94
95         $_[0]->handle($id, $fromnode, $msgid, $_[1]);
96         return;
97 }
98
99 sub handle
100 {
101         no strict 'subs';
102         my $self = shift;
103         my $id = 0 + shift;
104         my $sub = "handle$id";
105         $self->$sub($self, @_) if $self->can($sub);
106         return;
107 }
108
109 sub gen
110 {
111         no strict 'subs';
112         my $self = shift;
113         my $id = 0 + shift;
114         my $sub = "gen$id";
115         $self->$sub($self, @_) if $self->can($sub);
116         return;
117 }
118
119 my $last_node_update = 0;
120 my $node_update_interval = 60*15;
121
122 sub process
123 {
124         if ($main::systime >= $last_node_update+$node_update_interval) {
125 #               sendallnodes();
126 #               sendallusers();
127                 $last_node_update = $main::systime;
128         }
129 }
130
131 sub disconnect
132 {
133         my $self = shift;
134         $self->DXProt::disconnect(@_);
135 }
136
137 sub sendallnodes
138 {
139 }
140
141 sub sendallusers
142 {
143
144 }
145
146 my $msgid = 1;
147
148 sub frame
149 {
150         my $pcno = shift;
151         my $ht;
152         
153         $ht = sprintf "%X", $msgid;
154         my $line = join '^', sprintf("QX%02d", $pcno), $main::mycall, $ht, @_;
155         my $cs = sprintf "%02X", unpack("%32C*", $line) & 255;
156         $msgid = 1 if ++$msgid > 0xffff;
157         return "$line^$cs";
158 }
159
160 sub handle1
161 {
162         my $self = shift;
163         
164         my @f = split /\^/, $_[2];
165         my $inv = Verify->new($f[5]);
166         unless ($inv->verify($main::me->user->passphrase, $f[6], $main::mycall, $self->call)) {
167                 $self->sendnow('D','Sorry...');
168                 $self->disconnect;
169         }
170         if ($self->{outbound}) {
171                 $self->send($self->gen1);
172         } 
173         if ($self->{sort} ne 'S' && $f[2] eq 'DXSpider') {
174                 $self->{user}->{sort} = $self->{sort} = 'S';
175                 $self->{user}->{priv} = $self->{priv} = 1 unless $self->{priv};
176         }
177         $self->{version} = $f[3];
178         $self->{build} = $f[4];
179         $self->state('normal');
180         $self->{lastping} = 0;
181 }
182
183 sub gen1
184 {
185         my $self = shift;
186         my $inp = Verify->new;
187         return frame(1, 1, "DXSpider", $main::version + 53, $main::build, $inp->challenge, $inp->response($self->user->passphrase, $self->call, $main::mycall));
188 }
189
190 sub handle2
191 {
192
193 }
194
195 sub gen2
196 {
197         my $self = shift;
198         
199         my $node = shift;
200         my $sort = shift;
201         my @out;
202         my $dxchan;
203         
204         while (@_) {
205                 my $str = '';
206                 for (; @_ && length $str <= 230;) {
207                         my $ref = shift;
208                         my $call = $ref->call;
209                         my $flag = 0;
210                         
211                         $flag += 1 if $ref->here;
212                         $flag += 2 if $ref->conf;
213                         if ($ref->is_node) {
214                                 my $ping = int($ref->pingave * 10);
215                                 $str .= "^N$flag$call,$ping";
216                                 my $v = $ref->build || $ref->version;
217                                 $str .= ",$v" if defined $v;
218                         } else {
219                                 $str .= "^U$flag$call";
220                         }
221                 }
222                 push @out, $str if $str;
223         }
224         my $n = @out;
225         my $h = get_hops(90);
226         @out = map { sprintf "PC90^%s^%X^%s%d%s^%s^", $node->call, $main::systime, $sort, --$n, $_, $h } @out;
227         return @out;
228 }
229
230 1;