82cb2075d8f8196edf32524b048b96dbc7ca445c
[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,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->genI);
71 }
72
73 sub normal
74 {
75         if ($_[1] =~ /^PC\d\d\^/) {
76                 DXProt::normal(@_);
77                 return;
78         }
79         my ($sort, $tonode, $fromnode, $msgid, $incs);
80         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})$/;
81
82         $msgid = hex $msgid;
83         my $noderef = Route::Node::get($fromnode);
84         $noderef = Route::Node::new($fromnode) unless $noderef;
85
86         my $il = length $incs; 
87         my $cs = sprintf("%02X", unpack("%32C*", substr($_[1], 0, length($_[1]) - ($il+1))) & 255);
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($sort, $tonode, $fromnode, $msgid, $_[1]);
96         return;
97 }
98
99 sub handle
100 {
101         no strict 'subs';
102         my $self = shift;
103         my $sort = shift;
104         my $sub = "handle$sort";
105         $self->$sub(@_) if $self->can($sub);
106         return;
107 }
108
109 sub gen
110 {
111         no strict 'subs';
112         my $self = shift;
113         my $sort = shift;
114         my $sub = "gen$sort";
115         $self->$sub(@_) 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 my $msgid = 1;
138
139 sub frame
140 {
141         my $sort = shift;
142         my $to = shift || "*";
143         my $ht;
144         
145         $ht = sprintf "%X", $msgid;
146         my $line = join '^', "QX$sort", $to, $main::mycall, $ht, @_;
147         my $cs = sprintf "%02X", unpack("%32C*", $line) & 255;
148         $msgid = 1 if ++$msgid > 0xffff;
149         return "$line^$cs";
150 }
151
152 sub handleI
153 {
154         my $self = shift;
155         
156         my @f = split /\^/, $_[3];
157         my $inv = Verify->new($f[7]);
158         unless ($inv->verify($f[8], $main::me->user->passphrase, $main::mycall, $self->call)) {
159                 $self->sendnow('D','Sorry...');
160                 $self->disconnect;
161         }
162         if ($self->{outbound}) {
163                 $self->send($self->genI);
164         } 
165         if ($self->{sort} ne 'S' && $f[4] eq 'DXSpider') {
166                 $self->{user}->{sort} = $self->{sort} = 'S';
167                 $self->{user}->{priv} = $self->{priv} = 1 unless $self->{priv};
168         }
169         $self->{version} = $f[5];
170         $self->{build} = $f[6];
171         $self->state('init1');
172         $self->{lastping} = 0;
173 }
174
175 sub genI
176 {
177         my $self = shift;
178         my $inp = Verify->new;
179         return frame('I', $self->call, "DXSpider", ($main::version + 53) * 100, $main::build, $inp->challenge, $inp->response($self->user->passphrase, $self->call, $main::mycall));
180 }
181
182 sub handleR
183 {
184
185 }
186
187 sub genR
188 {
189
190 }
191
192 sub handleP
193 {
194
195 }
196
197 sub genP
198 {
199
200 }
201
202 sub gen2
203 {
204         my $self = shift;
205         
206         my $node = shift;
207         my $sort = shift;
208         my @out;
209         my $dxchan;
210         
211         while (@_) {
212                 my $str = '';
213                 for (; @_ && length $str <= 230;) {
214                         my $ref = shift;
215                         my $call = $ref->call;
216                         my $flag = 0;
217                         
218                         $flag += 1 if $ref->here;
219                         $flag += 2 if $ref->conf;
220                         if ($ref->is_node) {
221                                 my $ping = int($ref->pingave * 10);
222                                 $str .= "^N$flag$call,$ping";
223                                 my $v = $ref->build || $ref->version;
224                                 $str .= ",$v" if defined $v;
225                         } else {
226                                 $str .= "^U$flag$call";
227                         }
228                 }
229                 push @out, $str if $str;
230         }
231         my $n = @out;
232         my $h = get_hops(90);
233         @out = map { sprintf "PC90^%s^%X^%s%d%s^%s^", $node->call, $main::systime, $sort, --$n, $_, $h } @out;
234         return @out;
235 }
236
237 1;