File Coverage

blib/lib/Net/DirectConnect/adc.pm
Criterion Covered Total %
statement 39 405 9.6
branch 0 244 0.0
condition 0 255 0.0
subroutine 13 51 25.4
pod 0 2 0.0
total 52 957 5.4


line stmt bran cond sub pod time code
1             #$Id: adc.pm 1001 2014-05-07 13:08:30Z pro $ $URL: svn://svn.setun.net/dcppp/trunk/lib/Net/DirectConnect/adc.pm $
2             package #hide from cpan
3             Net::DirectConnect::adc;
4 1     1   2106 use strict;
  1         3  
  1         53  
5 1     1   5 no strict qw(refs);
  1         3  
  1         32  
6 1     1   5 use warnings "NONFATAL" => "all";
  1         3  
  1         54  
7 1     1   5 no warnings qw(uninitialized);
  1         2  
  1         51  
8 1     1   6 no if $] >= 5.017011, warnings => 'experimental::smartmatch';
  1         3  
  1         10  
9 1     1   61 use Time::HiRes qw(time sleep);
  1         3  
  1         11  
10 1     1   178 use Socket;
  1         2  
  1         856  
11 1     1   7 use Data::Dumper; #dev only
  1         3  
  1         81  
12             $Data::Dumper::Sortkeys = $Data::Dumper::Useqq = $Data::Dumper::Indent = 1;
13             #eval "use MIME::Base32 qw( RFC ); 1;" or print join ' ', ( 'err', 'cant use', $@ );
14             #use MIME::Base32 qw( RFC );
15 1     1   6 use Net::DirectConnect;
  1         3  
  1         27  
16             #use Net::DirectConnect::clicli;
17 1     1   645 use Net::DirectConnect::http;
  1         3  
  1         41  
18             #use Net::DirectConnect::httpcli;
19 1     1   935 use lib::abs('pslib');
  1         1511  
  1         7  
20 1     1   1532 use psmisc; # REMOVE
  1         4  
  1         152  
21             our $VERSION = ( split( ' ', '$Revision: 1001 $' ) )[1];
22 1     1   8 use base 'Net::DirectConnect';
  1         2  
  1         8552  
23             our %codesSTA = (
24             '00' => 'Generic, show description',
25             'x0' => 'Same as 00, but categorized according to the rough structure set below',
26             '10' => 'Generic hub error',
27             '11' => 'Hub full',
28             '12' => 'Hub disabled',
29             '20' => 'Generic login/access error',
30             '21' => 'Nick invalid',
31             '22' => 'Nick taken',
32             '23' => 'Invalid password',
33             '24' => 'CID taken',
34             '25' =>
35             'Access denied, flag "FC" is the FOURCC of the offending command. Sent when a user is not allowed to execute a particular command',
36             '26' => 'Registered users only',
37             '27' => 'Invalid PID supplied',
38             '30' => 'Kicks/bans/disconnects generic',
39             '31' => 'Permanently banned',
40             '32' =>
41             'Temporarily banned, flag "TL" is an integer specifying the number of seconds left until it expires (This is used for kick as well…).',
42             '40' => 'Protocol error',
43             '41' =>
44             qq{Transfer protocol unsupported, flag "TO" the token, flag "PR" the protocol string. The client receiving a CTM or RCM should send this if it doesn't support the C-C protocol. },
45             '42' =>
46             qq{Direct connection failed, flag "TO" the token, flag "PR" the protocol string. The client receiving a CTM or RCM should send this if it tried but couldn't connect. },
47             '43' => 'Required INF field missing/bad, flag "FM" specifies missing field, "FB" specifies invalid field.',
48             '44' => 'Invalid state, flag "FC" the FOURCC of the offending command.',
49             '45' => 'Required feature missing, flag "FC" specifies the FOURCC of the missing feature.',
50             '46' => 'Invalid IP supplied in INF, flag "I4" or "I6" specifies the correct IP.',
51             '47' => 'No hash support overlap in SUP between client and hub.',
52             '50' => 'Client-client / file transfer error',
53             '51' => 'File not available',
54             '52' => 'File part not available',
55             '53' => 'Slots full',
56             '54' => 'No hash support overlap in SUP between clients.',
57             );
58             #eval "use Net::DirectConnect::TigerHash; 1;" or print join ' ', ( 'err', 'cant use', $@ );
59             #eval q{use Net::DirectConnect::TigerHash;};
60              
61             =no
62             sub base32 ($) {
63             #eval {
64             MIME::Base32::encode( $_[0] );
65             #; } || @_;
66             }
67              
68             sub tiger ($) {
69             local ($_) = @_;
70             #use Mhash qw( mhash mhash_hex MHASH_TIGER);
71             #eval "use MIME::Base32 qw( RFC ); use Digest::Tiger;" or $self->log('err', 'cant use', $@);
72             #$_.=("\x00"x(1024 - length $_)); print ( 'hlen', length $_);
73             #Digest::Tiger::hash($_);
74             eval { Net::DirectConnect::TigerHash::tthbin($_); }
75             #mhash(Mhash::MHASH_TIGER, $_);
76             }
77             sub hash ($) { base32( tiger( $_[0] ) ); }
78             =cut
79              
80             #sub init { my $self = shift;
81              
82             =cu
83             sub new {
84             #psmisc::printlog('adc::new', @_);
85             ## my $self = ref $_[0] ? shift() : bless {}, $_[0];
86             my $self = ref $_[0] ? shift() : Net::DirectConnect->new(
87             #@_
88             adcinit(bless({},shift),@_)
89             ); #
90              
91             #shift if $_[0] eq __PACKAGE__;
92             return $self;
93              
94             }
95             =cut
96             sub func {
97 0 0   0 0   my $self = shift if ref $_[0];
98             #warn 'func call';
99             #$self->log( 'func s=', $self, $self->{number});
100 0           $self->SUPER::func(@_);
101 0           %_ = ( 'ID_file' => 'ID', );
102 0   0       $self->{$_} //= $_{$_} for keys %_;
103 0 0         if ( Net::DirectConnect::use_try('Crypt::Rhash') ) {
104 0           eval q{
105             $self->{hash} ||= sub { shift if ref $_[0];
106             Crypt::Rhash->new(Crypt::Rhash::RHASH_TTH)->update($_[0])->hash(Crypt::Rhash::RHASH_TTH, Crypt::Rhash::RHPR_BASE32 | Crypt::Rhash::RHPR_UPPERCASE);
107             };
108             $self->{hash_file} ||= sub { shift if ref $_[0];
109             Crypt::Rhash->new(Crypt::Rhash::RHASH_TTH)->update_file($_[0])->hash(Crypt::Rhash::RHASH_TTH, Crypt::Rhash::RHPR_BASE32 | Crypt::Rhash::RHPR_UPPERCASE);
110             };
111             };
112             }
113 0 0         if ( Net::DirectConnect::use_try( 'MIME::Base32', 'RFC' ) ) {
114             $self->{base_encode} ||= sub {
115 0 0   0     shift if ref $_[0];
116 0           MIME::Base32::encode_rfc3548(@_);
117 0   0       };
118             $self->{base_decode} ||= sub {
119 0 0   0     shift if ref $_[0];
120 0           MIME::Base32::decode_rfc3548(@_);
121 0   0       };
122             } else {
123 0           our $warned;
124 0 0         $self->log( 'err', 'cant use MIME::Base32' ) unless $warned++;
125             }
126 0 0         if ( Net::DirectConnect::use_try('Net::DirectConnect::TigerHash') ) {
127 0 0 0 0     $self->{hash} ||= sub { shift if ref $_[0]; Net::DirectConnect::TigerHash::tthbin( $_[0] ); };
  0            
  0            
128 0 0   0     $self->{hash_file} ||= sub { shift if ref $_[0];
129 0           Net::DirectConnect::TigerHash::tthfile($_[0]);
130 0   0       };
131             $self->{base_encode} ||= sub {
132 0 0   0     shift if ref $_[0];
133 0           Net::DirectConnect::TigerHash::toBase32( $_[0] );
134 0   0       };
135             $self->{base_decode} ||= sub {
136 0 0   0     shift if ref $_[0];
137 0           Net::DirectConnect::TigerHash::fromBase32( $_[0] );
138 0   0       };
139             } else {
140             #$self->log( 'err', 'cant use Net::DirectConnect::TigerHash' );
141             }
142 0 0 0 0     $self->{hash_base} ||= sub { shift if ref $_[0]; $self->base_encode( $self->hash( $_[0] ) ) };
  0            
  0            
143             #sub hash ($) { base32( tiger( $_[0] ) ); }
144             $self->{cmd_direct} ||= sub {
145 0 0   0     my $self = shift if ref $_[0];
146 0           my $peerid = shift;
147 0 0 0       local $self->{'host'} = $self->{'peers'}{$peerid}{'INF'}{I4}, local $self->{'port'} = $self->{'peers'}{$peerid}{'INF'}{U4}
148             if $self->{'peers'}{$peerid}{'INF'}{I4} and $self->{'peers'}{$peerid}{'INF'}{U4};
149 0           $self->cmd(@_);
150 0   0       };
151             $self->{ID_get} ||= sub {
152             #sub ID_get {
153 0 0   0     my $self = shift if ref $_[0];
154 0 0 0       if ( -s $self->{'ID_file'} ) { $self->{'ID'} ||= psmisc::file_read( $self->{'ID_file'} ); }
  0            
155 0 0         unless ( $self->{'ID'} ) {
156 0   0       $self->{'ID'} ||= join ' ', 'perl', $self->{'myip'}, $VERSION, $0, $self->{'INF'}{'NI'}, time,
157             '$Id: adc.pm 1001 2014-05-07 13:08:30Z pro $';
158 0           psmisc::file_rewrite( $self->{'ID_file'}, $self->{'ID'} );
159             }
160 0   0       $self->{'PID'} ||= $self->hash( $self->{'ID'} );
161 0   0       $self->{'CID'} ||= $self->hash( $self->{'PID'} );
162 0   0       $self->{'INF'}{'PD'} ||= $self->base_encode( $self->{'PID'} );
163 0   0       $self->{'INF'}{'ID'} ||= $self->base_encode( $self->{'CID'} );
164 0           return $self->{'ID'};
165 0   0       };
166             #$self->log( 'sub igen ', );
167             $self->{INF_generate} ||= sub {
168 0 0   0     my $self = shift if ref $_[0];
169             #$self->log( 'dev', 'inf_generate', $self->{'myport'},$self->{'myport_udp'},$self->{'myport_sctp'}, $self->{'myip'}, Dumper $self->{'INF'});
170             #$self->{'clients'}{'listener_udp'}
171 0   0       $self->{'INF'}{'NI'} ||= $self->{'Nick'} || 'perlAdcDev';
      0        
172 0 0 0       $self->{'PID'} ||= MIME::Base32::decode $self->{'INF'}{'PD'} if $self->{'INF'}{'PD'};
173 0 0 0       $self->{'CID'} ||= MIME::Base32::decode $self->{'INF'}{'ID'} if $self->{'INF'}{'ID'};
174 0           $self->ID_get();
175 0 0 0       $self->{'INF'}{'SID'} ||= $self->{broadcast} ? $self->{'INF'}{'ID'} : substr $self->{'INF'}{'ID'}, 0, 4;
176             #sid
177             #$self->log( 'id gen',"iID=$self->{'INF'}{'ID'} iPD=$self->{'INF'}{'PD'} PID=$self->{'PID'} CID=$self->{'CID'} ID=$self->{'ID'}" );
178 0   0       $self->{'INF'}{'SL'} ||= $self->{'S'} || '2';
      0        
179 0   0       $self->{'INF'}{'SS'} ||= $self->{'sharesize'} || 20025693588;
      0        
180 0   0       $self->{'INF'}{'SF'} ||= 30999;
181 0   0       $self->{'INF'}{'HN'} ||= $self->{'H'} || 1;
      0        
182 0   0       $self->{'INF'}{'HR'} ||= $self->{'R'} || 0;
      0        
183 0   0       $self->{'INF'}{'HO'} ||= $self->{'O'} || 0;
      0        
184 0   0       $self->{'INF'}{'VE'} ||= $self->{'client'} . $self->{'V'}
      0        
185             || 'perl'
186             . $Net::DirectConnect::VERSION . '_'
187             . $VERSION; #. '_' . ( split( ' ', '$Revision: 1001 $' ) )[1]; #'++\s0.706';
188 0   0       $self->{'INF'}{'US'} ||= 10000;
189             #my $domain = '4';
190 0           my $domaindel = '4';
191              
192             #if ( $self->{'myip'} =~ /:/ ) {
193             #$domain = '6';
194             #$domaindel = '4';
195             #}
196 0 0 0       for my $domain ($self->{dev_ipv6} || $self->{'myip'} =~ /:/ ? (qw(4 6)) : (4)) {
197 0   0       $self->{'INF'}{ 'U' . $domain } = $self->{'myport_udp'} || $self->{'myport'}; #maybe if broadcast only
198 0           $self->{'INF'}{ 'I' . $domain } = $self->{'myip'};
199 0           $self->{'INF'}{ 'S' . $domain } = $self->{'myport_sctp'}; # if $self->{'myport_sctp'};
200             }
201 0           delete $self->{'INF'}{ $_ . $domaindel } for qw(I);
202 0 0         if ( $self->{'ipv6_only'} ) {
203 0           delete $self->{'INF'}{ $_ . $domaindel } for qw(U S);
204             }
205 0 0 0       $self->{'INF'}{'SU'} ||= join ',', keys %{ $self->{'SU'} || {} };
  0            
206 0           return $self->{'INF'};
207 0   0       };
208             #$self->log( 'func end', );
209             }
210              
211             sub init {
212 0 0   0 0   my $self = shift if ref $_[0];
213             #$self->log( 'init s=', $self, $self->{number}, __PACKAGE__);
214             #shift if $_[0] eq __PACKAGE__;
215             #print "adcinit SELF=", $self, "REF=", ref $self, " P=", @_, "package=", __PACKAGE__, "\n\n";
216             #$self->SUPER::new();
217             #%$self = (
218             #%$self,
219 0           local %_ = (
220             'Nick' => 'NetDCBot',
221             'port' => 1511,
222             'host' => 'localhost',
223             'protocol' => 'adc',
224             'adc' => 1,
225             #'Pass' => '',
226             #'key' => 'zzz',
227             #'auto_wait' => 1,
228             'reconnects' => 99999, 'search_every' => 10, 'search_every_min' => 10, 'auto_connect' => 1,
229             #ADC
230             'protocol_connect' => 'ADC/1.0',
231             'protocol_supported' => { 'ADC/1.0' => 'adc' },
232             'message_type' => 'H',
233             #@_,
234             'incomingclass' => __PACKAGE__, #'Net::DirectConnect::adc',
235             no_print => { 'INF' => 1, 'QUI' => 1, 'SCH' => 1, },
236             'ID_file' => 'ID',
237             'cmd_bef' => undef,
238             'cmd_aft' => "\x0A",
239             'auto_say_cmd' => [qw(MSG)],
240             );
241 0   0       $self->{$_} //= $_{$_} for keys %_;
242             #!exists $self->{$_} ? $self->{$_} ||= $_{$_} : () for keys %_;
243             #print 'adc init now=',Dumper $self;
244             $self->{'periodic'}{ __FILE__ . __LINE__ } = sub {
245 0 0   0     my $self = shift if ref $_[0];
246 0 0         $self->search_buffer() if $self->{'socket'};
247 0           };
248             #$self->log( $self, 'inited', "MT:$self->{'message_type'}", ' with', Dumper \@_ );
249             #$self->baseinit(); #if ref $self eq __PACKAGE__;
250             #$self->log( 'inited3', "MT:$self->{'message_type'}", ' with' );
251 0           $self->{SUPAD}{H}{$_} = $_ for qw(BAS0 BASE TIGR UCM0 BLO0 BZIP );
252 0           $self->{SUPAD}{I}{$_} = $_ for qw(BASE TIGR BZIP);
253 0           $self->{SUPAD}{C}{$_} = $_ for qw(BASE TIGR BZIP);
254 0           $self->{SU}{$_} = $_ for qw(ADC0 TCP4 UDP4);
255 0 0         if ( $self->{'broadcast'} ) { $self->{SUPAD}{B} = $self->{SUPAD}{C};
  0            
256 0           $self->{'myport'} = $self->{'port'};
257              
258             }
259 0 0         if ( $self->{'hub'} ) { # hub listener
    0          
260             #$self->log( 'dev', 'hub settings apply');
261 0           $self->{'auto_connect'} = 0;
262 0           $self->{'auto_listen'} = 1;
263 0           $self->{'status'} = 'working';
264 0           $self->{'disconnect_recursive'} = 1;
265             } elsif ( $self->{parent}{hub} ) { # hub client
266             #$self->log( 'dev', 'hubparent:', $self->{parent}{hub});
267 0           $self->{message_type} = 'B';
268             } else {
269 0           $self->module_load('filelist');
270             }
271             #if ($self->{'message_type'} eq 'H') {
272             # $self->{'disconnect_recursive'} = 1;
273             #}
274             #$self->{$_} ||= $self->{'parent'}{$_} ||= {} for qw(peers peers_sid peers_cid want share_full share_tth);
275 0   0       $self->{$_} ||= $self->{'parent'}{$_} for qw(ID PID CID INF SUPAD myport ipv6_only);
276             # Proto
277 0 0         $self->{message_type} = 'B' if $self->{'broadcast'};
278             #$self->log( 'funci', );
279             #$self->func();
280 0           $self->Net::DirectConnect::adc::func();
281 0 0         if ( $self->{dev_sctp} ) {
282 0           $self->{SU}{$_} = $_ for qw(SCTP4);
283             }
284             #if ( $self->{dev_ipv6} ) {
285 0           $self->{SU}{$_} = $_ for qw(TCP6 UDP6);
286 0 0         if ( $self->{dev_sctp} ) {
287 0           $self->{SU}{$_} = $_ for qw(SCTP6);
288             }
289             #}
290             #warn "IG:$self->{INF_generate}";
291             #$self->log( 'igen', $self->{INF_generate});
292 0           $self->INF_generate();
293             $self->{'parse'} ||= {
294             #
295             #=================
296             #ADC dev
297             #
298             #'ISUP' => sub { }, 'ISID' => sub { $self->{'INF'}{'SID'} = $_[0] }, 'IINF' => sub { $self->cmd('BINF') }, 'IQUI' => sub { }, 'ISTA' => sub { $self->log( 'dcerr', @_ ) },
299             'SUP' => sub {
300 0 0   0     my $self = shift if ref $_[0];
301 0           my ( $dst, $peerid ) = @{ shift() };
  0            
302             #for my $feature (split /\s+/, $_[0])
303             #$self->log( 'adcdev', $dst, 'SUP:', @_ , "SID:n=$self->{'number'}; $peerid, $self->{'status'}");
304             #=z
305             #if $self->{''}
306 0 0         if ( $dst eq 'H' ) {
    0          
307 0           $self->cmd( 'I', 'SUP' );
308             #$peerid ||= join '', map {} 1..4
309 0   0       $peerid ||= $self->base_encode(
310             pack 'S', $self->{'number'}
311             #+ int rand 100
312             );
313             #$self->log( 'adcdevsid', "pack [$self->{'number'}] = [$peerid]" );
314 0           $peerid = ( 'A' x ( 4 - length $peerid ) ) . $peerid;
315 0   0       $self->{'peerid'} ||= $peerid;
316             #$self->log( 'adcdev', $dst, 'SUP:', @_, "SID:n=$self->{'number'}; $peerid=$self->{'peerid'}" );
317 0           $self->cmd( 'I', 'SID', $peerid );
318 0           $self->cmd( 'I', 'INF', ); #$self->{'peers'}{$_}{'INF'}
319             #for keys %{$self->{'peers'}};
320 0           $self->{'status'} = 'connected';
321             } elsif ( $dst eq 'C' ) {
322 0           $self->cmd( $dst, 'SUP', ); #unless $self->{count_sendcmd}{CSUP};
323 0 0         $self->cmd( $dst, 'INF', ) unless $self->{count_sendcmd}{CINF};
324             }
325 0   0       $peerid ||= '';
326 0           for ( $self->adc_strings_decode(@_) ) {
327 0 0         if ( (s/^(AD|RM)//)[0] eq 'RM' ) { delete $self->{'peers'}{$peerid}{'SUP'}{$_}; }
  0            
328 0           else { $self->{'peers'}{$peerid}{'SUP'}{$_} = 1; }
329             }
330             #=cut
331              
332             =z
333             my $params = $self->adc_parse_named(@_);
334             for ( keys %$params ) {
335             delete $self->{'peers'}{$peerid}{'SUP'}{ $params->{$_} } if $_ eq 'RM';
336             $self->{'peers'}{$peerid}{'SUP'}{ $params->{$_} } = 1 if $_ eq 'AD';
337             }
338             =cut
339              
340             #$self->log('adcdev', 'SUPans:', $peerid, $self->{'peers'}{$peerid}{'INF'}{I4}, $self->{'peers'}{$peerid}{'INF'}{U4});
341             #local $self->{'host'} = $self->{'peers'}{$peerid}{'INF'}{I4}; #can answer direct
342             #local $self->{'port'} = $self->{'peers'}{$peerid}{'INF'}{U4};
343             #$self->cmd( 'D', 'INF', ) if $self->{'broadcast'} and $self->{'broadcast_INF'};
344             #$self->cmd_direct( 'D', 'INF', ) if $self->{'broadcast'} and $self->{'broadcast_INF'};
345 0           return $self->{'peers'}{$peerid}{'SUP'};
346             },
347             'SID' => sub {
348 0 0   0     my $self = shift if ref $_[0];
349 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
350             #$self->log('devv', '( $dst, $peerid, $toid ) = ', "( $dst, $peerid, $toid )");
351 0 0         return $self->{'INF'}{'SID'} unless $dst eq 'I';
352 0           $self->{'INF'}{'SID'} = $_[0];
353             #$self->log( 'adcdev', 'SID:', $self->{'INF'}{'SID'}, $dst );
354 0 0         if ( $dst eq 'I' ) {
355 0           $self->cmd( 'B', 'INF' );
356 0           $self->{'status'} = 'connected'; #clihub
357             }
358 0           return $self->{'INF'}{'SID'};
359             },
360             'INF' => sub {
361 0 0   0     my $self = shift if ref $_[0];
362 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
363             #test $_[1] eq 'I'!
364             #$self->log('adcdev', '0INF:', "[d=$dst,p=$peerid]", join ':', @_);
365             #$self->log('adcdev', 'INF1', $peerid, @_);
366 0           my $params = $self->adc_parse_named(@_);
367             #$self->log('adcdev', 'INF2', $peerid, @_);
368             #for (@_) {
369             #s/^(\w\w)//;
370             #my ($code)= $1;
371             #$self->log('adcdev', 'INF:', $dst, $peerid, $toid, Dumper $params);
372             #$self->{'peers'}{$peerid}{'INF'}{$code} = $_;
373             #}
374 0           my $peersid = $peerid;
375 0 0 0       if ( $dst ne 'B' and $peerid ||= $params->{ID} ) {
      0        
376 0           $self->log( 'adcdev', 'INF:', "moving peer '' to $peerid" );
377 0   0       $self->{'peerid'} ||= $peerid;
378 0 0         $self->{'peers'}{$peerid}{$_} = $self->{'peers'}{''}{$_} for keys %{ $self->{'peers'}{''} || {} };
  0            
379 0           delete $self->{'peers'}{''};
380             }
381             #$self->log( 'adcdev', 'INF:', "existing '' peer: $peerid" ) if $self->{'peers'}{''};
382 0           my $sendbinf;
383 0 0 0       if ( $self->{parent}{hub} and $dst eq 'B' ) {
384 0 0         if ( !keys %{ $self->{'peers'}{$peerid}{'INF'} } ) { #join
  0            
385             #++$sendbinf;
386             #$self->log( 'adcdev', 'FIRSTINF:', $peerid, Dumper $params, $self->{'peers'} );
387 0           $self->cmd( 'B', 'INF', $_, $self->{'peers_sid'}{$_}{'INF'} ) for keys %{ $self->{'peers_sid'} };
  0            
388             }
389             }
390             #$dst eq 'I' ?
391 0 0         my $v = $self->{hostip} =~ /:/ ? '6' : '4';
392 0 0 0       $self->log( 'adcdev', "ip change from [$params->{qq{I$v}}] to [$self->{hostip}] " ), $params->{"I$v"} = $self->{hostip}
      0        
      0        
393             if $dst eq 'B'
394             and $self->{parent}{hub}
395             and $params->{"I$v"}
396             and $params->{"I$v"} ne $self->{hostip}; #!$self->{parent}{hub}
397 0 0         $v = $self->{recv_hostip} =~ /:/ ? '6' : '4';
398 0 0         if ( #$dst eq 'B' and
399             $self->{broadcast}
400             )
401             {
402 0           $self->log( 'adcdev',
403             "ip change from [$params->{qq{I$v}}] to [$self->{recv_hostip}:$self->{recv_port}] ($self->{recv_hostip}:$self->{port})"
404             );
405             #$params->{U4} = $self->{recv_port};
406 0   0       $params->{"U$v"} ||= $self->{port};
407 0   0       $params->{"I$v"} ||= $self->{recv_hostip};
408             }
409 0 0 0       if ( $peerid eq $self->{'INF'}{'SID'} and !$self->{myip} ) {
410 0   0       $self->{myip} ||= $params->{I4};
411 0   0       $self->{'INF'}{'I4'} ||= $params->{I4};
412 0           $self->log( 'adcdev', "ip detected: [$self->{myip}:$self->{myport}]" );
413             }
414             #my $first_seen;
415             #$first_seen = 1 unless $self->{'peers'}{$peerid}{INF};
416             #$self->log( 'adcdev', "peer[$first_seen]: $peerid : $self->{'peers'}{$peerid}");
417 0           $self->{'peers'}{$peerid}{'INF'}{$_} = $params->{$_} for keys %$params;
418 0           $self->{'peers'}{$peerid}{'object'} = $self;
419 0   0       $self->{'peers'}{ $params->{ID} } ||= $self->{'peers'}{$peerid};
420 0   0       $self->{'peers'}{$peerid}{'SID'} ||= $peersid;
421 0   0       $self->{'peers_sid'}{$peersid} ||= $self->{'peers'}{$peerid};
422 0   0       $self->{'peers_cid'}{ $self->{'peers'}{$peerid}{'INF'}{'ID'} } ||= $self->{'peers'}{$peerid};
423             #$self->log( 'adcdev', 'INF:', $peerid, Dumper $params, $self->{'peers'} ) unless $peerid;
424             #$self->log('adcdev', 'INF7', $peerid, @_);
425             #if ( $dst eq 'I' ) {
426             # $self->cmd( 'B', 'INF' );
427             # $self->{'status'} = 'connected'; #clihub
428             #} els
429 0 0         if ( $dst eq 'C' ) {
430 0           $self->{'status'} = 'connected'; #clicli
431 0 0         $self->cmd( $dst, 'INF' ) unless $self->{count_sendcmd}{CINF};
432 0 0         if ( $params->{TO} ) { }
433             else { }
434 0           $self->file_select();
435 0           $self->cmd( $dst, 'GET' );
436             }
437             #$self->log('adcdev', 'INF8', $peerid, @_);
438             #if ($sendbinf) { $self->cmd( 'B', 'INF', $_, $self->{'peers_sid'}{$_}{'INF'} ) for keys %{ $self->{'peers_sid'} }; }
439             #$self->log('adcdev', 'INF9', $peerid, "H:$self->{parent}{hub}", @_);
440 0 0         if ( $self->{parent}{hub} ) {
441 0           my $params_send = \%$params;
442 0           delete $params_send->{PD};
443 0           $self->cmd_all( $dst, 'INF', $peerid, $self->adc_make_string($params_send) );
444             }
445             #$self->log('adcdev', "first_seen: $first_seen,$peerid ne $self->{'INF'}{'SID'} dst: $dst");
446 0 0 0       if ( #$first_seen and
      0        
447             $self->{'broadcast'} and $peerid ne $self->{'INF'}{'SID'} and $dst eq 'B'
448             )
449             {
450 0 0         $self->cmd( 'D', 'INF', ) if $self->{'broadcast'}; # and $self->{'broadcast_INF'};
451             #$self->cmd_direct( $peerid, 'D', 'INF', ) if $self->{'broadcast'} and $self->{'broadcast_INF'};
452             }
453 0           return $params; #$self->{'peers'}{$peerid}{'INF'};
454             },
455             'QUI' => sub {
456 0 0   0     my $self = shift if ref $_[0];
457 0           my ( $dst, $peerid ) = @{ shift() };
  0            
458             #$peerid
459             #$self->log( 'adcdev', 'QUI', $dst, $_[0], Dumper $self->{'peers'}{ $_[0] } );
460 0           delete $self->{'peers_cid'}{ $self->{'peers'}{$peerid}{'INF'}{'ID'} };
461 0           delete $self->{'peers_sid'}{$peerid};
462 0           delete $self->{'peers'}{$peerid}; # or mark time
463 0           undef;
464             },
465             'STA' => sub {
466 0 0   0     my $self = shift if ref $_[0];
467 0           my ( $dst, $peerid ) = @{ shift() };
  0            
468             #$self->log( 'dcerr', @_ );
469 0           my $code = shift;
470 0           $code =~ s/^(.)//;
471 0           my $severity = $1;
472             #TODO: $severity :
473             #0 Success (used for confirming commands), error code must be "00", and an additional flag "FC" contains the FOURCC of the command being confirmed if applicable.
474             #1 Recoverable (error but no disconnect)
475             #2 Fatal (disconnect)
476             #my $desc = $self->{'codesSTA'}{$code};
477 0           @_ = $self->adc_strings_decode(@_);
478             #$self->log( 'adcdev', 'STA', $peerid, $severity, 'c=', $code, 't=',@_, "=[$Net::DirectConnect::adc::codesSTA{$code}]" );
479 0 0 0       if ( $code ~~ '20' and $_[0] =~ /^Reconnecting too fast, you have to wait (\d+) seconds before reconnecting./ ) {
    0 0        
480 0           $self->work( $1 + 10 );
481             } elsif ( $code ~~ '30'
482             and $_[0] =~
483             /^You are disconnected because: You are disconnected for hammering the hub with connect attempts, stop or you'll be kicked !!!/ # 'mc
484             )
485             {
486 0           $self->work(30);
487             }
488 0           return $severity, $code, $Net::DirectConnect::adc::codesSTA{$code}, @_;
489             },
490             'SCH' => sub {
491 0 0   0     my $self = shift if ref $_[0];
492 0           my ( $dst, $peerid, @feature ) = @{ shift() };
  0            
493             #$self->log( 'adcdev', 'SCH', ( $dst, $peerid, 'F=>', @feature ), 'S=>', @_ );
494 0           $self->cmd_all( $dst, 'SCH', $peerid, @feature, @_ );
495 0           my $params = $self->adc_parse_named(@_);
496             #DRES J3F4 KULX SI0 SL57 FN/Joculete/logs/stderr.txt TRLWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ TOauto
497 0   0       my $found = $self->{'share_full'}{ $params->{TR} } || $self->{'share_full'}{ $params->{AN} };
498 0           my $tth = $self->{'share_tth'}{$found};
499 0 0         if (
500             #$self->{'share_full'} and $params->{TR} and exists $self->{'share_full'}{ $params->{TR} } and -s $self->{'share_full'}{ $params->{TR} }
501             $found
502             )
503             {
504 0 0         my $foundshow = ( $found =~ m{^/} ? () : '/' ) . (
505             #$self->{chrarset_fs} ?
506             #$self->{charset_fs} ne $self->{charset_protocol} ?
507             Encode::encode $self->{charset_protocol}, Encode::decode( $self->{charset_fs}, $found, Encode::FB_WARN ),
508             Encode::FB_WARN
509             #: $found
510             );
511 0           $self->log( 'adcdev', 'SCH', ( $dst, $peerid, 'F=>', @feature ),
512             $found, -s $found, -e $found, 'c=', $self->{chrarset_fs}, );
513 0   0       local @_ = ( {
      0        
      0        
514             SI => ( -s $found ) || -1,
515             SL => $self->{INF}{SL},
516             FN => $self->adc_path_encode($foundshow),
517             TO => $params->{TO} || $self->make_token($peerid),
518             TR => $params->{TR} || $tth,
519             }
520             );
521 0 0 0       if ( $self->{'peers'}{$peerid}{INF}{I4} and $self->{'peers'}{$peerid}{INF}{U4} ) {
522 0           $self->log(
523             'dcdev', 'SCH', 'i=', $self->{'peers'}{$peerid}{INF}{I4},
524             'u=', $self->{'peers'}{$peerid}{INF}{U4},
525             'T==>', 'U' . 'RES ' . $self->adc_make_string( $self->{'INF'}{'ID'}, @_ )
526             );
527 0           $self->send_udp(
528             $self->{'peers'}{$peerid}{INF}{I4}, $self->{'peers'}{$peerid}{INF}{U4},
529             'U' . 'RES ' . $self->adc_make_string( $self->{'INF'}{'ID'}, @_ ) #. $self->{'cmd_aft'}
530             );
531             } else {
532 0           $self->cmd( 'D', 'RES', $self->adc_make_string( $peerid, @_ ) );
533             }
534             }
535             #$self->adc_make_string(@_);
536             #TODO active send udp
537 0           return $params;
538             #TRKU2OUBVHC3VXUNOHO2BS2G4ECHYB6ESJUQPYFSY TO626120869 ]
539             #TRQYKHJIZEPSISFF3T25DIGKEYI645Y7PGMSI7QII TOauto ]
540             #ANthe ANhossboss TO3951841973 ]
541             #FSCH ABWN +TCP4 TRKX55JDOFEBX32GLBSITTSY6KUCK4NMPU2R4XUII TOauto
542             },
543             'RES' => sub {
544 0 0   0     my $self = shift if ref $_[0];
545 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
546             #test $_[1] eq 'I'!
547             #$self->log( 'adcdev', '0RES:', "[d=$dst,p=$peerid,t=$toid]", join ':', @_ );
548 0           my $params = $self->adc_parse_named(@_);
549             #$self->log('adcdev', 'RES:',"[d=$dst,p=$peerid]",Dumper $params);
550 0 0 0       if ( $dst eq 'D' and $self->{'parent'}{'hub'} and ref $self->{'peers'}{$toid}{'object'} ) {
      0        
551 0           $self->{'peers'}{$toid}{'object'}->cmd( 'D', 'RES', $peerid, $toid, @_ );
552             } else {
553             #= $1 if
554             #$params->{'FN'} =~ m{([^/\\]+)$};
555 0           $params->{CID} = $peerid;
556 0           ( $params->{'filename'} ) = $params->{FN} =~ m{([^\\/]+)$};
557 0   0       my $wdl = $self->{'want_download'}{ $params->{'TR'} } || $self->{'want_download'}{ $params->{'filename'} };
558 0 0         if ($wdl) { #exists $self->{'want_download'}{ $params->{'TR'} } ) {
559             #$self->{'want_download'}{ $params->{'TR'} }
560 0           $wdl->{$peerid} = $params; #maybe not all
561 0 0         if ( $params->{'filename'} ) { ++$self->{'want_download_filename'}{ $params->{TR} }{ $params->{'filename'} }; }
  0            
562 0           $self->{'want_download'}{ $params->{TR} }{$peerid} = $params; # _tth_from
563             }
564             }
565 0           $params;
566             },
567             'MSG' => sub {
568 0 0   0     my $self = shift if ref $_[0];
569 0           my ( $dst, $peerid ) = @{ shift() };
  0            
570             #@_ = map {adc_string_decode} @_;
571 0           $self->cmd_all( $dst, 'MSG', $peerid, @_ );
572 0           @_ = $self->adc_strings_decode(@_);
573 0           $self->log( 'adcdev', $dst, 'MSG', $peerid, "<" . $self->{'peers'}{$peerid}{'INF'}{'NI'} . '>', @_ );
574 0           @_;
575             },
576             'RCM' => sub {
577 0 0   0     my $self = shift if ref $_[0];
578 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
579 0   0       $toid ||= shift;
580             #$self->log( 'dcdev', "RCM( $dst, RCM, $peerid, $toid me=[$self->{'INF'}{'SID'}:$self->{'myport'}] )", @_ );
581 0 0 0       $self->cmd( $dst, 'CTM', $peerid, $self->{'protocol_supported'}{ $_[0] } || $self->{'protocol_connect'},
582             $self->{'myport'}, $_[1], )
583             if $toid eq $self->{'INF'}{'SID'};
584 0 0 0       if ( $dst eq 'D' and $self->{'parent'}{'hub'} and ref $self->{'peers'}{$toid}{'object'} ) {
      0        
585 0           $self->{'peers'}{$toid}{'object'}->cmd( 'D', 'RCM', $peerid, $toid, @_ );
586             }
587              
588             =z
589             my $host= $self->{'peers'}{$toid}{I4};
590             my $port= $self->{'peers'}{$toid}{U4}
591             $self->{'clients'}{ $host . ':' . $port } = __PACKAGE__->new(
592             #%$self, $self->clear(),
593             'parent' => $self,
594             'host' => $host,
595             'port' => $port,
596             #'want' => \%{ $self->{'want'} },
597             #'NickList' => \%{ $self->{'NickList'} },
598             #'IpList' => \%{ $self->{'IpList'} },
599             #'PortList' => \%{ $self->{'PortList'} },
600             #'handler' => \%{ $self->{'handler'} },
601             'auto_connect' => 1,
602             );
603             =cut
604              
605             },
606             'CTM' => sub {
607 0 0   0     my $self = shift if ref $_[0];
608 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
609 0   0       $toid ||= shift;
610 0 0 0       if ( $dst eq 'D' and $self->{'parent'}{'hub'} and ref $self->{'peers'}{$toid}{'object'} ) {
      0        
611 0           return $self->{'peers'}{$toid}{'object'}->cmd( 'D', 'CTM', $peerid, $toid, @_ );
612             }
613 0           my ( $proto, $port, $token ) = @_;
614 0           my $host = $self->{'peers'}{$peerid}{'INF'}{'I4'};
615 0           $self->log(
616             'dcdev',
617             "( $dst, CTM, $peerid, $toid ) - ($proto, $port, $token) me=$self->{'INF'}{'SID'} p=",
618             $self->{'protocol_supported'}{$proto}
619             );
620 0 0         $self->log( 'dcerr', 'CTM: unknown host', "( $dst, CTM, $peerid, $toid ) - ($proto, $port, $token)" ) unless $host;
621 0           $self->{'clients'}{ $self->{'peers'}{$peerid}{'INF'}{ID} or $host . ':' . $port } = __PACKAGE__->new(
622             #%$self, $self->clear(),
623             protocol => $self->{'protocol_supported'}{$proto} || 'adc',
624             parent => $self,
625             'host' => $host,
626             'port' => $port,
627             #'parse' => $self->{'parse'},
628             #'cmd' => $self->{'cmd'},
629             #'want' => $self->{'want'},
630             #'want' => \%{ $self->{'want'} },
631             #'NickList' => \%{ $self->{'NickList'} },
632             #'IpList' => \%{ $self->{'IpList'} },
633             #'PortList' => \%{ $self->{'PortList'} },
634             #'handler' => \%{ $self->{'handler'} },
635             #'TO' => $token,
636 0 0 0       'INF' => { %{ $self->{'INF'} }, 'TO' => $token },
      0        
637             'message_type' => 'C',
638             'auto_connect' => 1,
639             'reconnects' => 0,
640             no_listen => 1,
641             ) if $toid eq $self->{'INF'}{'SID'};
642             },
643             'SND' => sub {
644 0 0   0     my $self = shift if ref $_[0];
645 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
646             #CSND file files.xml.bz2 0 6117
647 0   0       $self->{'filetotal'} //= $_[2] + $_[3];
648 0           return $self->file_open();
649             },
650             #CGET file TTH/YDIXOH7A3W233WTOQUET3JUGMHNBYNFZ4UBXGNY 637534208 6291456
651             'GET' => sub {
652 0 0   0     my $self = shift if ref $_[0];
653 0           my ( $dst, $peerid, $toid ) = @{ shift() };
  0            
654 0           $self->file_send_parse(@_);
655              
656             =z
657             if ( $_[0] eq 'file' ) {
658             my $file = $_[1];
659             if ( $file =~ s{^TTH/}{} ) { $self->file_send_tth( $file, $_[2], $_[3] ); }
660             else {
661             #$self->file_send($file, $_[2], $_[3]);
662             }
663             } else {
664             $self->log( 'dcerr', 'SND', "unknown type", @_ );
665             }
666             =cut
667              
668             },
669 0   0       };
670              
671             =COMMANDS
672              
673              
674              
675              
676              
677              
678              
679              
680             =cut
681              
682             $self->{'cmd'} = {
683             #move to main
684             'search_send' => sub {
685 0 0   0     my $self = shift if ref $_[0];
686 0 0         $self->cmd_adc( 'B', 'SCH', @{ $_[0] || $self->{'search_last'} } );
  0            
687             #$self->send_udp(inet_ntoa(INADDR_BROADCAST), $self->{'dev_broadcast'}, $self->adc_make_string( 'BSCH', @{ $_[0] || $self->{'search_last'} })) if $self->{'dev_broadcast'};
688             },
689             'search_tth' => sub {
690 0 0   0     my $self = shift if ref $_[0];
691 0           $self->{'search_last_string'} = undef;
692 0           $self->log( 'search_tth', @_ );
693 0           local $_ = shift;
694 0 0         if ( $self->{'adc'} ) { $self->search_buffer( { TO => $self->make_token(), TR => $_, @_ } ); } #toauto
  0            
695             else {
696             #$self->cmd( 'search_buffer', 'F', 'T', '0', '9', 'TTH:' . $_[0] );
697             }
698             },
699             'search_string' => sub {
700 0 0   0     my $self = shift if ref $_[0];
701 0           my $string = shift;
702 0 0         if ( $self->{'adc'} ) {
703             #$self->cmd( 'search_buffer', { TO => 'auto', map AN => $_, split /\s+/, $string } );
704 0           $self->search_buffer( ( map { 'AN' . $_ } split /\s+/, $string ), { TO => $self->make_token(), @_ } ); #TOauto
  0            
705             } else {
706             #$self->{'search_last_string'} = $string;
707             #$string =~ tr/ /$/;
708             #$self->cmd( 'search_buffer', 'F', 'T', '0', '1', $string );
709             }
710             },
711             #'make_hub' => sub {
712             #my $self = shift if ref $_[0];
713             #$self->{'hub'} ||= $self->{'host'} . ( ( $self->{'port'} and $self->{'port'} != 411 ) ? ':' . $self->{'port'} : '' );
714             #},
715             'nick_generate' => sub {
716 0 0   0     my $self = shift if ref $_[0];
717 0   0       $self->{'nick_base'} ||= $self->{'Nick'};
718 0   0       $self->{'Nick'} = $self->{'nick_base'} . int( rand( $self->{'nick_random'} || 100 ) );
719             },
720             #
721             #=================
722             #ADC dev
723             #
724             'connect_aft' => sub {
725             #print "RUNADC![$self->{'protocol'}:$self->{'adc'}]";
726 0 0   0     my $self = shift if ref $_[0];
727             #$self->log( $self, 'connect_aft inited', "MT:$self->{'message_type'}", ' :', $self->{'broadcast'}, $self->{'parent'}{'hub'} );
728             #{
729 0           $self->cmd( $self->{'message_type'}, 'SUP' );
730             #}
731 0 0         if ( $self->{'broadcast'} ) { $self->cmd( $self->{'message_type'}, 'INF' ); }
  0            
732             #$self->cmd( $self->{'message_type'}, 'SUP' ) if $self->{'parent'}{'hub'};
733             #else
734             },
735             'accept_aft' => sub {
736             #print "RUNADC![$self->{'protocol'}:$self->{'adc'}]";
737 0 0   0     my $self = shift if ref $_[0];
738             #$self->log($self, 'accept_aft inited',"MT:$self->{'message_type'}", ' :', $self->{'broadcast'}, $self->{'parent'}{'hub'});
739             #{
740             #$self->cmd( $self->{'message_type'}, 'SUP' );
741             #}
742             #$self->cmd( $self->{'message_type'}, 'INF' );
743             },
744             'cmd_all' => sub {
745 0 0   0     my $self = shift if ref $_[0];
746             return if #( $_[0] ne 'B' and $_[0] ne 'F' and $_[0] ne 'I' ) or
747 0 0         !$self->{'parent'}{'hub'};
748 0           $self->{'parent'}->sendcmd_all(@_); #for keys %{ $self->{'peers_sid'} };
749             },
750             'SUP' => sub {
751 0 0   0     my $self = shift if ref $_[0];
752 0           my $dst = shift;
753             #$self->log($self, 'SUP inited',"MT:$self->{'message_type'}", "=== $dst");
754             #$self->{SUPADS} ||= [qw(BASE TIGR)] if $dst eq 'I'; #PING
755             #$self->{SUPADS} ||= [qw(BAS0 BASE TIGR UCM0 BLO0 BZIP )]; #PING ZLIG
756             #$self->{SUPRMS} ||= [qw()];
757             #$self->{SUP} ||= { ( map { $_ => 1 } @{ $self->{'SUPADS'} } ), ( map { $_ => 0 } @{ $self->{'SUPRMS'} } ) };
758             #$self->{'SUPAD'} ||= { map { $_ => 1 } @{ $self->{'SUPADS'} } };
759             #$self->cmd_adc( $dst, 'SUP', ( map { 'AD' . $_ } @{ $self->{'SUPADS'} } ), ( map { 'RM' . $_ } keys %{ $self->{'SUPRM'} } ), );
760             #$self->log( 'SUP', "sidp=[$self->{'INF'}{'SID'}]");
761             #{
762 0 0         local $self->{'INF'}{'SID'} = undef unless $self->{'broadcast'};
763 0           $self->cmd_adc(
764             $dst, 'SUP',
765 0           ( map { 'AD' . $_ } sort keys %{ $self->{SUPAD}{$dst} } ),
  0            
766 0           ( map { 'RM' . $_ } sort keys %{ $self->{SUPRM}{$dst} } ),
  0            
767             );
768             #}
769             #$self->log( 'SUP', "sida=[$self->{'INF'}{'SID'}]");
770             #ADBAS0 ADBASE ADTIGR ADUCM0 ADBLO0
771             },
772             'SID' => sub {
773 0 0   0     my $self = shift if ref $_[0];
774 0           my $dst = shift;
775             #$self->{'peerid'}
776 0           local $self->{'INF'}{'SID'} = undef; #!? unless $self->{'broadcast'};
777 0   0       $self->cmd_adc( $dst, 'SID', $_[0] || $self->{'peerid'} );
778             },
779             'INF' => sub {
780 0 0   0     my $self = shift if ref $_[0];
781 0           my $dst = shift;
782             #$self->{'BINFS'} ||= [qw(ID PD I4 I6 U4 U6 SS SF VE US DS SL AS AM EM NI DE HN HR HO TO CT AW SU RF)];
783             #$self->log('infsend', $dst, 'h=',$self->{parent}{hub});
784 0 0         if ( $self->{parent}{hub} ) {
785 0 0         if ( $dst eq 'I' ) {
    0          
786 0           $self->{'INF'} = { CT => 32, VE => 'perl' . $VERSION, NI => 'devhub', DE => 'hubdev', };
787             #IINF CT32 VEuHub/0.3.0-rc4\s(git:\sd2da49d...) NI"??????????\s?3\\14?" DE?????,\s??????,\s?????????.\s???\s????????\s-\s???\s????????.
788             } elsif ( $dst eq 'B' ) {
789 0           $self->cmd_adc #sendcmd
790             (
791             $dst, 'INF', #$self->{'INF'}{'SID'},
792             @_,
793             #map { $_ . $self->{'INF'}{$_} } $dst eq 'C' ? qw(ID TO) : sort keys %{ $self->{'INF'} }
794             );
795 0           return;
796             }
797             } else {
798 0           $self->INF_generate();
799             #$self->{''} ||= $self->{''} || '';
800             #$self->sendcmd( $dst, 'INF', $self->{'INF'}{'SID'}, map { $_ . $self->{$_} } grep { length $self->{$_} } @{ $self->{'BINFS'} } );
801             }
802             #$self->log(Dumper $self);
803             #$self->log('infsend inf', Dumper$self->{'INF'});
804 0           $self->cmd_adc #sendcmd
805             (
806             $dst, 'INF', #$self->{'INF'}{'SID'},
807 0 0         map { $_ . $self->{'INF'}{$_} } grep { length $self->{'INF'}{$_} } $dst eq 'C' ? qw(ID TO)
  0 0          
    0          
808             : @_ ? @_
809             : (
810             qw(ID I4 U4 I6 U6 S4 S6 SS SF VE US DS SL AS AM EM NI HN HR HO TO CT SU RF),
811             ( $self->{'message_type'} eq 'H' ? 'PD' : () )
812             ) #sort keys %{ $self->{'INF'} }
813             );
814             #grep { length $self->{$_} } @{ $self->{'BINFS'} } );
815             #$self->cmd_adc( $dst, 'INF', $self->{'INF'}{'SID'}, map { $_ . $self->{$_} } grep { $self->{$_} } @{ $self->{'BINFS'} } );
816             #BINF UUXX IDFXC3WTTDXHP7PLCCGZ6ZKBHRVAKBQ4KUINROXXI PDP26YAWX3HUNSTEXXYRGOIAAM2ZPMLD44HCWQEDY NIïûðûî SL2 SS20025693588
817             #SF30999 HN2 HR0 HO0 VE++\s0.706 US5242 SUADC0
818             },
819             'GET' => sub {
820 0 0   0     my $self = shift if ref $_[0];
821 0           my $dst = shift;
822             #$self->sendcmd( $dst, 'CTM', $self->{'protocol_connect'},@_);
823 0           local @_ = @_;
824 0 0         if ( !@_ ) {
825 0 0 0       @_ = ( 'file', $self->{'filename'}, $self->{'file_recv_from'} || '0', $self->{'file_recv_to'} || '-1' )
      0        
826             if $self->{'filename'};
827 0 0         $self->log( 'err', "Nothing to get" ), return unless @_;
828             }
829 0           $self->cmd_adc( $dst, 'GET', @_ );
830             },
831             'stat_hub' => sub {
832 0 0   0     my $self = shift if ref $_[0];
833 0           local %_;
834 0           for my $w (qw(SS SF)) {
835             #$self->log( 'dev', 'calc', $_, $w),
836 0 0         $_{$w} += $self->{'peers'}{$_}{INF}{$w} for grep { $_ and $_ ne $self->{'INF'}{'SID'} } keys %{ $self->{'peers_sid'} };
  0            
  0            
837             }
838 0           $_{UC} = keys %{ $self->{'peers'} };
  0            
839 0           return \%_;
840             },
841 0           };
842              
843             =auto
844             'CTM' => sub {
845             my $self = shift if ref $_[0];
846             my $dst = shift;
847             #$self->sendcmd( $dst, 'CTM', $self->{'protocol_connect'},@_);
848             $self->cmd_adc( $dst, 'CTM', @_ );
849             },
850             'RCM' => sub {
851             my $self = shift if ref $_[0];
852             my $dst = shift;
853             #$self->sendcmd( $dst, 'CTM', $self->{'protocol_connect'},@_);
854             $self->cmd_adc( $dst, 'RCM', @_ );
855             },
856             'SND' => sub {
857             my $self = shift if ref $_[0];
858             my $dst = shift;
859             #$self->sendcmd( $dst, 'CTM', $self->{'protocol_connect'},@_);
860             $self->cmd_adc( $dst, 'SND', @_ );
861             },
862             =cut
863              
864             #$self->log( 'dev', "0making listeners [$self->{'M'}]:$self->{'no_listen'}; auto=$self->{'auto_listen'}" );
865 0 0         if ( !$self->{'no_listen'} ) {
866             #$self->log( 'dev', 'nyportgen',"$self->{'M'} eq 'A' or !$self->{'M'} ) and !$self->{'auto_listen'} and !$self->{'incoming'}" );
867 0 0 0       if (
868             #( $self->{'M'} eq 'A' or !$self->{'M'} ) and
869             !$self->{'incoming'} and !$self->{'auto_listen'}
870             )
871             {
872             #$self->log( 'dev', __FILE__, __LINE__, " myptr", $self->{'auto_listen'}, $self->{broadcast});
873             #if (
874             #!$self->{'auto_listen'} or #$self->{'Proto'} ne 'tcp'
875             #$self->{broadcast}
876             # 1
877             # )
878             #{
879             #$self->log( 'dev', __FILE__, __LINE__, " myptr");
880 0           $self->log( 'dev', "making listeners: tcp; class=", $self->{'incomingclass'} );
881 0           $self->{'clients'}{'listener_tcp'} = $self->{'incomingclass'}->new(
882             'parent' => $self,
883             'protocol' => 'adc',
884             'auto_listen' => 1,
885             );
886             #$self->log( 'dev', __FILE__, __LINE__, " myptr");
887 0           $self->{'myport'} = $self->{'myport_tcp'} = $self->{'clients'}{'listener_tcp'}{'myport'};
888 0 0         $self->log( 'err', "cant listen tcp (file transfers)" ) unless $self->{'myport_tcp'};
889             #}
890             #if (
891             # !$self->{'auto_listen'}
892             #and $self->{'Proto'} ne 'udp'
893             # )
894             #{
895 0           $self->log( 'dev', "making listeners: udp ($self->{'auto_listen'})" );
896 0           $self->{'clients'}{'listener_udp'} = $self->{'incomingclass'}->new(
897             'parent' => $self,
898             'Proto' => 'udp',
899             'protocol' => 'adc',
900             'auto_listen' => 1,
901             #$self->{'clients'}{''} = $self->{'incomingclass'}->new( %$self, $self->clear(),
902             #'LocalPort'=>$self->{'myport'},
903             #'debug'=>1,
904             #'nonblocking' => 0,
905             #'NONONOparse' => {
906             #'SR' => $self->{'parse'}{'SR'},
907             #'PSR' => sub { #U
908             # #$self->log( 'dev', "UPSR", @_ );
909             #},
910             #2008/12/14-13:30:50 [3] rcv: welcome UPSR FQ2DNFEXG72IK6IXALNSMBAGJ5JAYOQXJGCUZ4A NIsss2911 HI81.9.63.68:4111 U40 TRZ34KN23JX2BQC2USOTJLGZNEWGDFB327RRU3VUQ PC4 PI0,64,92,94,100,128,132,135 RI64,65,66,67,68,68,69,70,71,72
911             #UPSR CDARCZ6URO4RAZKK6NDFTVYUQNLMFHS6YAR3RKQ NIAspid HI81.9.63.68:411 U40 TRQ6SHQECTUXWJG5ZHG3L322N5B2IV7YN2FG4YXFI PC2 PI15,17,20,128 RI128,129,130,131
912             #$SR [Predator]Wolf DC++\Btyan Adams - Please Forgive Me.mp314217310 18/20TTH:G7DXSTGPHTXSD2ZZFQEUBWI7PORILSKD4EENOII (81.9.63.68:4111)
913             #2008/12/14-13:30:50 welcome UPSR FQ2DNFEXG72IK6IXALNSMBAGJ5JAYOQXJGCUZ4A NIsss2911 HI81.9.63.68:4111 U40 TRZ34KN23JX2BQC2USOTJLGZNEWGDFB327RRU3VUQ PC4 PI0,64,92,94,100,128,132,135 RI64,65,66,67,68,68,69,70,71,72
914             #UPSR CDARCZ6URO4RAZKK6NDFTVYUQNLMFHS6YAR3RKQ NIAspid HI81.9.63.68:411 U40 TRQ6SHQECTUXWJG5ZHG3L322N5B2IV7YN2FG4YXFI PC2 PI15,17,20,128 RI128,129,130,131
915             #$SR [Predator]Wolf DC++\Btyan Adams - Please Forgive Me.mp314217310 18/20TTH:G7DXSTGPHTXSD2ZZFQEUBWI7PORILSKD4EENOII (81.9.63.68:4111)
916             #},
917             );
918 0           $self->{'myport_udp'} = $self->{'clients'}{'listener_udp'}{'myport'};
919             #$self->log( 'dev', 'nyportgen', $self->{'myport_udp'} );
920 0 0         $self->log( 'err', "cant listen udp (search repiles)" ) unless $self->{'myport_udp'};
921             #}
922 0 0         if (
923             #!$self->{'auto_listen'} and
924             $self->{'dev_sctp'}
925             )
926             {
927 0           $self->log( 'dev', "making listeners: sctp", "h=$self->{'hub'}" );
928 0           $self->{'clients'}{'listener_sctp'} = $self->{'incomingclass'}->new(
929             'parent' => $self,
930             'Proto' => 'sctp',
931             'protocol' => 'adc',
932             'auto_listen' => 1,
933             );
934 0           $self->{'myport_sctp'} = $self->{'clients'}{'listener_sctp'}{'myport'};
935             #$self->log( 'dev', 'nyportgen', $self->{'myport_sctp'} );
936 0 0         $self->log( 'err', "cant listen sctp" ) unless $self->{'myport_sctp'};
937             }
938             }
939             #DEV=z
940              
941             =no
942             if ( $self->{'dev_broadcast'} ) {
943             $self->log( 'info', 'listening broadcast ', $self->{'dev_broadcast'} || $self->{'port'});
944             $self->{'clients'}{'listener_udp_broadcast'} = $self->{'incomingclass'}->new(
945             #%$self, $self->clear(),
946             'parent' => $self, 'Proto' => 'udp', 'auto_listen' => 1,
947             'sockopts' => {%{$self->{'sockopts'}||{}}, 'Broadcast'=>1},
948             myport => $self->{'dev_broadcast'} || $self->{'port'},
949             );
950             $self->log( 'err', "cant listen broadcast (hubless)" ) unless $self->{'clients'}{'listener_udp_broadcast'}{'myport'};
951             }
952             =cut
953              
954 0 0         if ( $self->{'dev_http'} ) {
955 0           $self->log( 'dev', "making listeners: http" );
956             #$self->{'clients'}{'listener_http'} = Net::DirectConnect::http->new(
957 0   0       $self->{'clients'}{'listener_http'} = Net::DirectConnect->new(
      0        
958             #%$self, $self->clear(),
959             #'want' => \%{ $self->{'want'} },
960             #'NickList' => \%{ $self->{'NickList'} },
961             #'IpList' => \%{ $self->{'IpList'} },
962             ## 'PortList' => \%{ $self->{'PortList'} },
963             #'handler' => \%{ $self->{'handler'} },
964             #$self->{'clients'}{''} = $self->{'incomingclass'}->new( %$self, $self->clear(),
965             #'LocalPort'=>$self->{'myport'},
966             #'debug'=>1,
967             #@_,
968             'incomingclass' => 'Net::DirectConnect::http',
969             'auto_connect' => 0,
970             'auto_listen' => 1,
971             'protocol' => 'http',
972             #'auto_listen' => 1,
973             #'HubName' => 'Net::DirectConnect test hub',
974             #'myport' => 80,
975             'myport' => Net::DirectConnect::notone( $self->{'dev_http'} ) || 8000,
976             'myport_base' => Net::DirectConnect::notone( $self->{'dev_http'} ) || 8000,
977             'myport_random' => 99,
978             'myport_tries' => 5,
979             'parent' => $self,
980             #'allow' => ( $self->{http_allow} || '127.0.0.1' ),
981             #'auto_listen' => 0,
982             );
983 0           $self->{'myport_http'} = $self->{'clients'}{'listener_http'}{'myport'};
984 0 0         $self->log( 'err', "cant listen http" ) unless $self->{'myport_http'};
985             }
986 0 0 0       if ( $self->{'hub'} and $self->{'dev_sctp'} ) {
987 0           $self->log( 'dev', "making listeners: fallback tcp; $self->{'incomingclass'}" );
988 0           $self->{'clients'}{'listener_tcp'} = $self->{'incomingclass'}->new(
989             'parent' => $self,
990             'Proto' => 'tcp',
991 0           ( map { $_ => $self->{$_} } qw(myport hub) ),
992             'auto_listen' => 1,
993             );
994 0           $self->{'myport_tcp'} = $self->{'clients'}{'listener_tcp'}{'myport'};
995             #$self->log( 'dev', 'nyportgen_tcp', $self->{'myport_tcp'} );
996 0 0         $self->log( 'err', "cant listen tcp" ) unless $self->{'myport_tcp'};
997             }
998             }
999             #=cut
1000             $self->{'handler_int'}{'disconnect_aft'} = sub {
1001 0 0   0     my $self = shift if ref $_[0];
1002 0           my $peerid = $self->{'peerid'};
1003             #$self->log('dev', 'adc disconnecting', $peerid);
1004 0           delete $self->{'peers_cid'}{ $self->{'peers'}{$peerid}{'INF'}{'ID'} };
1005 0           delete $self->{'peers_sid'}{$peerid};
1006 0           delete $self->{'peers'}{ $self->{'peers'}{$peerid}{'INF'}{'ID'} };
1007 0           delete $self->{'peers'}{$peerid};
1008 0 0 0       $self->cmd_all( 'I', 'QUI', $self->{'peerid'}, ) if $self->{'parent'}{'hub'} and $self->{'peerid'};
1009 0 0         delete $self->{'INF'}{'SID'} unless $self->{'parent'};
1010             #$self->log(
1011             # 'dev', 'disconnect int', #psmisc::caller_trace(30)
1012             # 'hub=', $self->{'parent'}{'hub'},
1013             #); #if $self and $self->{'log'};
1014             #psmisc::caller_trace 15;
1015 0           };
1016 0 0         $self->get_peer_addr() if $self->{'socket'};
1017             #$self->log( 'err', 'cant load TigerHash module' ) if !$INC{'Net/DirectConnect/TigerHash.pm'} and !our $tigerhashreported++;
1018 0 0         $self->accept_aft() if $self->{'incoming'};
1019 0           return $self;
1020             }
1021             1;