~motu-torrent/azureus/upstream-stable

« back to all changes in this revision

Viewing changes to com/aelitis/azureus/core/versioncheck/VersionCheckClient.java

  • Committer: John Dong
  • Date: 2007-10-22 04:54:13 UTC
  • Revision ID: john.dong@gmail.com-20071022045413-3ovb11u82rrcokxx
Commit 3.0.3.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Created on Dec 20, 2004
3
 
 * Created by Alon Rohter
4
 
 * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License
8
 
 * as published by the Free Software Foundation; either version 2
9
 
 * of the License, or (at your option) any later version.
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
 
 * 
18
 
 * AELITIS, SAS au capital de 46,603.30 euros
19
 
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
20
 
 *
21
 
 */
22
 
 
23
 
package com.aelitis.azureus.core.versioncheck;
24
 
 
25
 
 
26
 
import java.io.BufferedInputStream;
27
 
import java.io.ByteArrayInputStream;
28
 
import java.io.ByteArrayOutputStream;
29
 
import java.io.IOException;
30
 
import java.io.InputStream;
31
 
import java.io.OutputStream;
32
 
import java.lang.reflect.InvocationTargetException;
33
 
import java.net.HttpURLConnection;
34
 
import java.net.InetAddress;
35
 
import java.net.InetSocketAddress;
36
 
import java.net.Socket;
37
 
import java.net.URL;
38
 
import java.net.URLEncoder;
39
 
import java.util.*;
40
 
 
41
 
import org.gudy.azureus2.core3.config.COConfigurationManager;
42
 
import org.gudy.azureus2.core3.internat.MessageText;
43
 
import org.gudy.azureus2.core3.logging.*;
44
 
import org.gudy.azureus2.core3.stats.transfer.*;
45
 
import org.gudy.azureus2.core3.util.*;
46
 
 
47
 
import org.gudy.azureus2.plugins.PluginInterface;
48
 
 
49
 
import com.aelitis.azureus.core.AzureusCoreFactory;
50
 
import com.aelitis.azureus.core.clientmessageservice.*;
51
 
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
52
 
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASNLookup;
53
 
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
54
 
import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
55
 
import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler;
56
 
 
57
 
 
58
 
 
59
 
/**
60
 
 * Client for checking version information from a remote server.
61
 
 */
62
 
public class VersionCheckClient {
63
 
        private static final LogIDs LOGID = LogIDs.CORE;
64
 
        
65
 
        public static final String      REASON_UPDATE_CHECK_START               = "us";
66
 
        public static final String      REASON_UPDATE_CHECK_PERIODIC    = "up";
67
 
        public static final String      REASON_CHECK_SWT                                = "sw";
68
 
        public static final String      REASON_DHT_EXTENDED_ALLOWED             = "dx";
69
 
        public static final String      REASON_DHT_ENABLE_ALLOWED               = "de";
70
 
        public static final String      REASON_EXTERNAL_IP                              = "ip";
71
 
        public static final String      REASON_RECOMMENDED_PLUGINS              = "rp";
72
 
        public static final String      REASON_SECONDARY_CHECK                  = "sc";
73
 
        
74
 
        
75
 
  private static final String   AZ_MSG_SERVER_ADDRESS   = "version.aelitis.com";
76
 
  private static final int              AZ_MSG_SERVER_PORT              = 27001;
77
 
  private static final String   MESSAGE_TYPE_ID                 = "AZVER";
78
 
  
79
 
  public static final String    HTTP_SERVER_ADDRESS     = "version.aelitis.com";
80
 
  public static final int               HTTP_SERVER_PORT                = 2080;
81
 
 
82
 
  public static final String    TCP_SERVER_ADDRESS              = "version.aelitis.com";
83
 
  public static final int               TCP_SERVER_PORT                 = 2080;
84
 
 
85
 
  public static final String    UDP_SERVER_ADDRESS              = "version.aelitis.com";
86
 
  public static final int               UDP_SERVER_PORT                 = 2080;
87
 
 
88
 
  
89
 
  private static final long             CACHE_PERIOD    = 5*60*1000;
90
 
  private static boolean secondary_check_done;
91
 
  
92
 
  
93
 
  static{
94
 
          VersionCheckClientUDPCodecs.registerCodecs();
95
 
  }
96
 
  
97
 
  private static final VersionCheckClient instance = new VersionCheckClient();
98
 
  private Map last_check_data = null;
99
 
  private final AEMonitor check_mon = new AEMonitor( "versioncheckclient" );
100
 
  private long last_check_time = 0; 
101
 
  
102
 
  
103
 
  private VersionCheckClient() {
104
 
    /* blank */
105
 
  }
106
 
  
107
 
  
108
 
  
109
 
  /**
110
 
   * Get the singleton instance of the version check client.
111
 
   * @return version check client
112
 
   */
113
 
  public static VersionCheckClient getSingleton() {  return instance;  }
114
 
  
115
 
  
116
 
  
117
 
  /**
118
 
   * Get the version check reply info.
119
 
   * @return reply data, possibly cached, if the server was already checked within the last minute
120
 
   */
121
 
  public Map getVersionCheckInfo( String reason ) {
122
 
          return( getVersionCheckInfoSupport( reason, false, false ));
123
 
  }
124
 
 
125
 
 
126
 
  protected Map 
127
 
  getVersionCheckInfoSupport( 
128
 
                  String        reason, 
129
 
                  boolean       only_if_cached, 
130
 
                  boolean       force )
131
 
  {
132
 
    try {  check_mon.enter();
133
 
    
134
 
      long time_diff = SystemTime.getCurrentTime() - last_check_time;
135
 
     
136
 
      force = force || time_diff > CACHE_PERIOD || time_diff < 0;
137
 
      
138
 
      if( last_check_data == null || last_check_data.size() == 0 || force ) {
139
 
          // if we've never checked before then we go ahead even if the "only_if_cached"
140
 
          // flag is set as its had not chance of being cached yet!
141
 
        if ( only_if_cached && last_check_data != null ){
142
 
                return( new HashMap() );
143
 
        }
144
 
        try {
145
 
          last_check_data = performVersionCheck( constructVersionCheckMessage( reason ), true, true );
146
 
        }
147
 
        catch( Throwable t ) {
148
 
          t.printStackTrace();
149
 
          last_check_data = new HashMap();
150
 
        }
151
 
      }
152
 
      else {
153
 
        Logger.log(new LogEvent(LOGID, "VersionCheckClient is using "
154
 
                                                + "cached version check info. Using " + last_check_data.size()
155
 
                                                + " reply keys.")); 
156
 
      }
157
 
    }
158
 
    finally {  check_mon.exit();  }
159
 
    
160
 
    if( last_check_data == null )  last_check_data = new HashMap();
161
 
    
162
 
    return last_check_data;
163
 
  }
164
 
  
165
 
  private boolean
166
 
  isVersionCheckDataValid()
167
 
  {     
168
 
        return( last_check_data != null && last_check_data.size() > 0 ); 
169
 
  }
170
 
  
171
 
  /**
172
 
   * Get the ip address seen by the version check server.
173
 
   * NOTE: This information may be cached, see getVersionCheckInfo().
174
 
   * @return external ip address, or empty string if no address information found
175
 
   */
176
 
  public String 
177
 
  getExternalIpAddress(
178
 
                boolean only_if_cached )
179
 
  {
180
 
    Map reply = getVersionCheckInfoSupport( REASON_EXTERNAL_IP, only_if_cached, false );
181
 
    
182
 
    byte[] address = (byte[])reply.get( "source_ip_address" );
183
 
    if( address != null ) {
184
 
      return new String( address );
185
 
    }
186
 
    
187
 
    return( null );
188
 
  }
189
 
  
190
 
  
191
 
  /**
192
 
   * Is the DHT plugin allowed to be enabled.
193
 
   * @return true if DHT can be enabled, false if it should not be enabled
194
 
   */
195
 
  public boolean DHTEnableAllowed() {
196
 
    Map reply = getVersionCheckInfo( REASON_DHT_ENABLE_ALLOWED );
197
 
    
198
 
    boolean     res = false;
199
 
    
200
 
    byte[] value = (byte[])reply.get( "enable_dht" );
201
 
    
202
 
    if( value != null ) {
203
 
        
204
 
      res = new String( value ).equalsIgnoreCase( "true" );
205
 
    }
206
 
    
207
 
        // we take the view that if the version check failed then we go ahead
208
 
        // and enable the DHT (i.e. we're being optimistic)
209
 
 
210
 
    if ( !res ){
211
 
        res = !isVersionCheckDataValid();
212
 
    }
213
 
    
214
 
    return res;
215
 
  }
216
 
  
217
 
  
218
 
  /**
219
 
   * Is the DHT allowed to be used by external plugins.
220
 
   * @return true if extended DHT use is allowed, false if not allowed
221
 
   */
222
 
  public boolean DHTExtendedUseAllowed() {
223
 
    Map reply = getVersionCheckInfo( REASON_DHT_EXTENDED_ALLOWED );
224
 
    
225
 
    boolean     res = false;
226
 
    
227
 
    byte[] value = (byte[])reply.get( "enable_dht_extended_use" );
228
 
    if( value != null ) {
229
 
      res = new String( value ).equalsIgnoreCase( "true" );
230
 
    }
231
 
    
232
 
        // be generous and enable extended use if check failed
233
 
    
234
 
    if ( !res ){
235
 
        res = !isVersionCheckDataValid();
236
 
    }
237
 
    
238
 
    return res;
239
 
  }
240
 
  
241
 
  public String[]
242
 
  getRecommendedPlugins()
243
 
  {
244
 
          Map reply = getVersionCheckInfo( REASON_RECOMMENDED_PLUGINS );
245
 
 
246
 
          List  l = (List)reply.get( "recommended_plugins" );
247
 
          
248
 
          if ( l == null ){
249
 
                  
250
 
                  return( new String[0] );
251
 
          }
252
 
          
253
 
          String[]      res = new String[l.size()];
254
 
          
255
 
          for (int i=0;i<l.size();i++){
256
 
                  
257
 
                  res[i] = new String((byte[])l.get(i));
258
 
          }
259
 
          
260
 
          return( res );
261
 
  }
262
 
  
263
 
  /**
264
 
   * Perform the actual version check by connecting to the version server.
265
 
   * @param data_to_send version message
266
 
   * @return version reply
267
 
   * @throws Exception if the server check connection fails
268
 
   */
269
 
  private Map 
270
 
  performVersionCheck( 
271
 
        Map     data_to_send,
272
 
        boolean use_az_message,
273
 
        boolean use_http ) 
274
 
  
275
 
        throws Exception 
276
 
  {
277
 
        Exception       error   = null;
278
 
        Map                     reply   = null;
279
 
        
280
 
        if ( use_az_message ){
281
 
        
282
 
                try{
283
 
                        reply = executeAZMessage( data_to_send );
284
 
                        
285
 
                        reply.put( "protocol_used", "AZMSG" );
286
 
                        
287
 
                }catch( Exception e ){
288
 
                
289
 
                        error = e;
290
 
                }
291
 
        }
292
 
        
293
 
        if ( reply == null && use_http ){
294
 
                
295
 
                try{
296
 
                        reply = executeHTTP( data_to_send );
297
 
                        
298
 
                        reply.put( "protocol_used", "HTTP" );
299
 
                        
300
 
                        error = null;
301
 
                        
302
 
                }catch( Exception e ){
303
 
                
304
 
                        error = e;
305
 
                        
306
 
                }
307
 
        }
308
 
        if ( error != null ){
309
 
                
310
 
                throw( error );
311
 
        }
312
 
      
313
 
        if (Logger.isEnabled())
314
 
                                Logger.log(new LogEvent(LOGID, "VersionCheckClient server "
315
 
                                                + "version check successful. Received " + reply.size()
316
 
                                                + " reply keys."));
317
 
 
318
 
    last_check_time = SystemTime.getCurrentTime();
319
 
      
320
 
    return reply;
321
 
  }
322
 
  
323
 
  private Map
324
 
  executeAZMessage(
325
 
        Map     data_to_send )
326
 
  
327
 
        throws Exception
328
 
  {
329
 
          if (Logger.isEnabled())
330
 
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
331
 
                                  + "version information from " + AZ_MSG_SERVER_ADDRESS + ":" + AZ_MSG_SERVER_PORT)); 
332
 
 
333
 
          ClientMessageService  msg_service = null;
334
 
          Map                                   reply           = null; 
335
 
 
336
 
          try{
337
 
                  msg_service = ClientMessageServiceClient.getServerService( AZ_MSG_SERVER_ADDRESS, AZ_MSG_SERVER_PORT, MESSAGE_TYPE_ID );
338
 
 
339
 
                  msg_service.sendMessage( data_to_send );  //send our version message
340
 
 
341
 
                  reply = msg_service.receiveMessage();  //get the server reply
342
 
 
343
 
                  preProcessReply( reply );
344
 
                  
345
 
          }finally{
346
 
 
347
 
                  if ( msg_service != null ){
348
 
 
349
 
                          msg_service.close();
350
 
                  }
351
 
          }
352
 
          
353
 
          return( reply );
354
 
  }
355
 
  
356
 
  private Map
357
 
  executeHTTP(
358
 
        Map     data_to_send )
359
 
  
360
 
        throws Exception
361
 
  {
362
 
          if (Logger.isEnabled())
363
 
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
364
 
                                  + "version information from " + HTTP_SERVER_ADDRESS + ":" + HTTP_SERVER_PORT + " via HTTP" )); 
365
 
 
366
 
          String        url_str = "http://" + HTTP_SERVER_ADDRESS + (HTTP_SERVER_PORT==80?"":(":" + HTTP_SERVER_PORT)) + "/version?";
367
 
 
368
 
          url_str += URLEncoder.encode( new String( BEncoder.encode( data_to_send ), "ISO-8859-1" ), "ISO-8859-1" );
369
 
          
370
 
          URL   url = new URL( url_str );
371
 
          
372
 
          HttpURLConnection     url_connection = (HttpURLConnection)url.openConnection();
373
 
          
374
 
          url_connection.connect();
375
 
          
376
 
          try{
377
 
                  InputStream   is = url_connection.getInputStream();
378
 
                  
379
 
                  Map   reply = BDecoder.decode( new BufferedInputStream( is ));
380
 
                  
381
 
                  preProcessReply( reply );
382
 
 
383
 
                  return( reply );
384
 
                  
385
 
          }finally{
386
 
                  
387
 
                  url_connection.disconnect();
388
 
          }
389
 
  }
390
 
  
391
 
  public String
392
 
  getHTTPGetString(
393
 
        boolean for_proxy )
394
 
  {
395
 
          return( getHTTPGetString( new HashMap(), for_proxy));
396
 
  }
397
 
  
398
 
  private String
399
 
  getHTTPGetString(
400
 
        Map             content,
401
 
        boolean for_proxy )
402
 
  {
403
 
          String        get_str = "GET " + (for_proxy?("http://" + HTTP_SERVER_ADDRESS + ":" + HTTP_SERVER_PORT ):"") +"/version?";
404
 
 
405
 
          try{
406
 
                  get_str += URLEncoder.encode( new String( BEncoder.encode( content ), "ISO-8859-1" ), "ISO-8859-1" );
407
 
                  
408
 
          }catch( Throwable e ){ 
409
 
          }
410
 
          
411
 
          get_str +=" HTTP/1.1" + "\015\012" + "\015\012";
412
 
         
413
 
          return( get_str );
414
 
  }
415
 
  
416
 
  private Map
417
 
  executeTCP(
418
 
        Map                             data_to_send,
419
 
        InetAddress             bind_ip,
420
 
        int                             bind_port )
421
 
  
422
 
        throws Exception
423
 
  {
424
 
          if (Logger.isEnabled())
425
 
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
426
 
                                  + "version information from " + TCP_SERVER_ADDRESS + ":" + TCP_SERVER_PORT + " via TCP" )); 
427
 
 
428
 
          String        get_str = getHTTPGetString( data_to_send, false );
429
 
          
430
 
          Socket        socket = null;
431
 
          
432
 
          try{
433
 
                  socket = new Socket();
434
 
                 
435
 
                  if ( bind_ip != null ){
436
 
                          
437
 
                          socket.bind( new InetSocketAddress( bind_ip, bind_port ));
438
 
                          
439
 
                  }else if ( bind_port != 0 ){
440
 
                          
441
 
                          socket.bind( new InetSocketAddress( bind_port ));
442
 
                  }
443
 
                  
444
 
                  socket.setSoTimeout( 10000 );
445
 
                
446
 
                  socket.connect( new InetSocketAddress( TCP_SERVER_ADDRESS, TCP_SERVER_PORT ), 10000 );
447
 
                  
448
 
                  OutputStream  os = socket.getOutputStream();
449
 
                  
450
 
                  os.write( get_str.getBytes( "ISO-8859-1" ));
451
 
                  
452
 
                  os.flush();
453
 
                  
454
 
                  InputStream   is = socket.getInputStream();
455
 
                  
456
 
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
457
 
                                
458
 
                  byte[]        buffer = new byte[1024];
459
 
 
460
 
                  int   total_len = 0;
461
 
                  
462
 
                  while( true ){
463
 
                          
464
 
                          int   len = is.read( buffer );
465
 
                          
466
 
                          if ( len <= 0 ){
467
 
                                  
468
 
                                  break;
469
 
                          }
470
 
                          
471
 
                          total_len += len;
472
 
                          
473
 
                          if ( total_len > 16000 ){
474
 
                                  
475
 
                                  throw( new IOException( "reply too large" ));
476
 
                          }
477
 
                          
478
 
                          baos.write( buffer, 0, len );
479
 
                  }
480
 
                  
481
 
                  byte[]        reply_bytes = baos.toByteArray();
482
 
                  
483
 
                  for (int i=3;i<reply_bytes.length;i++){
484
 
                          
485
 
                          if (          reply_bytes[i-3]== (byte)'\015' &&
486
 
                                                reply_bytes[i-2]== (byte)'\012' &&
487
 
                                                reply_bytes[i-1]== (byte)'\015' &&
488
 
                                                reply_bytes[i-0]== (byte)'\012' ){
489
 
                                          
490
 
                                  Map reply = BDecoder.decode( new BufferedInputStream( new ByteArrayInputStream( reply_bytes, i+1, reply_bytes.length - (i+1 ))));
491
 
                                  
492
 
                                  preProcessReply( reply );
493
 
 
494
 
                                  return( reply );
495
 
                          }
496
 
                  }
497
 
                  
498
 
                  throw( new Exception( "Invalid reply: " + new String( reply_bytes )));
499
 
                  
500
 
          }finally{
501
 
                  
502
 
                  if ( socket != null ){
503
 
                          
504
 
                          try{
505
 
                                  socket.close();
506
 
                                  
507
 
                          }catch( Throwable e ){
508
 
                                  
509
 
                          }
510
 
                  }
511
 
          }
512
 
  }
513
 
  
514
 
  private Map
515
 
  executeUDP(
516
 
        Map                             data_to_send,
517
 
        InetAddress             bind_ip,
518
 
        int                             bind_port )
519
 
  
520
 
        throws Exception
521
 
  {
522
 
          PRUDPReleasablePacketHandler handler = PRUDPPacketHandlerFactory.getReleasableHandler( bind_port );
523
 
                  
524
 
          PRUDPPacketHandler    packet_handler = handler.getHandler();
525
 
          
526
 
          long timeout = 5;
527
 
          
528
 
          Random random = new Random();
529
 
          
530
 
          try{
531
 
                  Exception     last_error = null;
532
 
                  
533
 
                  packet_handler.setExplicitBindAddress( bind_ip );       
534
 
                  
535
 
                  for (int i=0;i<3;i++){
536
 
                          
537
 
                          try{
538
 
                                        // connection ids for requests must always have their msb set...
539
 
                                        // apart from the original darn udp tracker spec....
540
 
                                  
541
 
                                  long connection_id = 0x8000000000000000L | random.nextLong();
542
 
                                  
543
 
                                  VersionCheckClientUDPRequest  request_packet = new VersionCheckClientUDPRequest( connection_id );
544
 
                                  
545
 
                                  request_packet.setPayload( data_to_send );
546
 
                                  
547
 
                                  VersionCheckClientUDPReply reply_packet = (VersionCheckClientUDPReply)packet_handler.sendAndReceive( null, request_packet, new InetSocketAddress( UDP_SERVER_ADDRESS, UDP_SERVER_PORT ), timeout );
548
 
                
549
 
                                  Map   reply = reply_packet.getPayload();
550
 
                                  
551
 
                                  preProcessReply( reply );
552
 
                                  
553
 
                                  return( reply );
554
 
                                  
555
 
                          }catch( Exception e){
556
 
                                  
557
 
                                  last_error    = e;
558
 
                                  
559
 
                                  timeout = timeout * 2;
560
 
                          }
561
 
                  }
562
 
                  
563
 
                  if ( last_error != null ){
564
 
                          
565
 
                          throw( last_error );
566
 
                  }
567
 
                  
568
 
                  throw( new Exception( "Timeout" ));
569
 
                  
570
 
          }finally{
571
 
                 
572
 
                  packet_handler.setExplicitBindAddress( null );
573
 
 
574
 
                  handler.release();
575
 
          }
576
 
  }
577
 
  
578
 
  protected void
579
 
  preProcessReply(
580
 
        Map             reply )
581
 
  {
582
 
                // two cases where we automatically attempt to resolve the ASN (to minimise load on ASN
583
 
                // provider)
584
 
                // 1) new installs
585
 
                // 2) where we have an asn and public IP has changed outside of prefix range
586
 
         
587
 
         final long ASN_MIN_CHECK = 7*24*60*60*1000L;
588
 
                 
589
 
         boolean        check_asn       = false;
590
 
         
591
 
         long now = SystemTime.getCurrentTime();
592
 
                 
593
 
         long   asn_check_time = COConfigurationManager.getLongParameter( "ASN Autocheck Performed Time" );
594
 
                         
595
 
         if ( now < asn_check_time || now - asn_check_time > ASN_MIN_CHECK ){
596
 
                 
597
 
                 String bgp_prefix      = COConfigurationManager.getStringParameter( "ASN BGP", null );
598
 
                 String asn                     = COConfigurationManager.getStringParameter( "ASN ASN", null );
599
 
                 
600
 
                 if (   asn == null || asn.length() == 0 ||
601
 
                                bgp_prefix == null || bgp_prefix.length() == 0 ){
602
 
                        
603
 
                                // during 2502 introduction we ran DNS based queries as fallback without support
604
 
                                // for reading ASN - pick up blank ASNs now and force recheck
605
 
                         
606
 
                         check_asn = true;
607
 
                         
608
 
                 }else{
609
 
                                                                 
610
 
                         try{
611
 
                                 byte[] address = (byte[])reply.get( "source_ip_address" );
612
 
                                  
613
 
                                 InetAddress    ip = InetAddress.getByName( new String( address ));
614
 
 
615
 
                                        // if we've got a prefix only recheck if outside existing range
616
 
                         
617
 
                                 if ( !NetworkAdmin.getSingleton().matchesCIDR( bgp_prefix, ip )){
618
 
                                 
619
 
                                         check_asn = true;
620
 
                                 }
621
 
                                 
622
 
                         }catch( Throwable e ){
623
 
                                 
624
 
                                 check_asn = true;
625
 
                                 
626
 
                                 Debug.printStackTrace(e);
627
 
                         }
628
 
                }
629
 
         }
630
 
         
631
 
         if ( check_asn ){
632
 
                 
633
 
                 COConfigurationManager.setParameter( "ASN Autocheck Performed Time", now );
634
 
 
635
 
                 try{
636
 
                         byte[] address = (byte[])reply.get( "source_ip_address" );
637
 
                          
638
 
                         InetAddress    ip = InetAddress.getByName( new String( address ));
639
 
                 
640
 
                         NetworkAdminASNLookup  asn = NetworkAdmin.getSingleton().lookupASN( ip );
641
 
                                                         
642
 
                         COConfigurationManager.setParameter( "ASN AS",         asn.getAS());
643
 
                         COConfigurationManager.setParameter( "ASN ASN",        asn.getASName());
644
 
                         COConfigurationManager.setParameter( "ASN BGP",        asn.getBGPPrefix());
645
 
                         
646
 
                                // kick off a secondary version check to communicate the new information
647
 
                         
648
 
                         if ( !secondary_check_done ){
649
 
                                 
650
 
                                 secondary_check_done   = true;
651
 
                                 
652
 
                                 new AEThread( "Secondary version check", true )
653
 
                                 {
654
 
                                         public void
655
 
                                         runSupport()
656
 
                                         {
657
 
                                                 getVersionCheckInfoSupport( REASON_SECONDARY_CHECK, false, true );
658
 
                                         }
659
 
                                 }.start();
660
 
                         }                       
661
 
                 }catch( Throwable e ){         
662
 
                         
663
 
                         Debug.printStackTrace(e);
664
 
                 }
665
 
         }
666
 
         
667
 
         Long   as_advice = (Long)reply.get( "as_advice" );
668
 
         
669
 
         if ( as_advice != null ){
670
 
                 
671
 
             String     asn = COConfigurationManager.getStringParameter( "ASN ASN", null );
672
 
 
673
 
             if ( asn != null ){
674
 
                
675
 
                         long   advice = as_advice.longValue();
676
 
                         
677
 
                         if ( advice != 0 ){
678
 
                        
679
 
                                        // require crypto
680
 
                                 
681
 
                                 String done_asn = COConfigurationManager.getStringParameter( "ASN Advice Followed", "" );
682
 
                                 
683
 
                                 if ( !done_asn.equals( asn )){
684
 
                                         
685
 
                                         COConfigurationManager.setParameter( "ASN Advice Followed", asn );
686
 
                                         
687
 
                                         boolean        change  = advice == 1 || advice == 2;
688
 
                                         boolean        alert   = advice == 1 || advice == 3;
689
 
                                         
690
 
                                         if ( !COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" )){
691
 
                                                 
692
 
                                                 if ( change ){
693
 
                                                         
694
 
                                                         COConfigurationManager.setParameter( "network.transport.encrypted.require", true );
695
 
                                                 }
696
 
                                                 
697
 
                                                 if ( alert ){
698
 
                                                         
699
 
                                                         String msg = 
700
 
                                                                 MessageText.getString(
701
 
                                                                                "crypto.alert.as.warning",
702
 
                                                                                new String[]{ asn });
703
 
                                                         
704
 
                                                         Logger.log( new LogAlert( false, LogAlert.AT_WARNING, msg ));
705
 
                                                 }
706
 
                                         }
707
 
                                 }
708
 
                         }
709
 
             }
710
 
         }
711
 
  }
712
 
  
713
 
  public InetAddress
714
 
  getExternalIpAddressHTTP()
715
 
  
716
 
        throws Exception
717
 
  {
718
 
          Map reply = executeHTTP( new HashMap());
719
 
          
720
 
          byte[] address = (byte[])reply.get( "source_ip_address" );
721
 
          
722
 
          return( InetAddress.getByName( new String( address )));
723
 
  }
724
 
  
725
 
  public InetAddress
726
 
  getExternalIpAddressTCP(
727
 
        InetAddress             bind_ip,
728
 
        int                             bind_port )
729
 
  
730
 
        throws Exception
731
 
  {
732
 
          Map reply = executeTCP( new HashMap(), bind_ip, bind_port );
733
 
          
734
 
          byte[] address = (byte[])reply.get( "source_ip_address" );
735
 
          
736
 
          return( InetAddress.getByName( new String( address )));
737
 
  }
738
 
  
739
 
  public InetAddress
740
 
  getExternalIpAddressUDP(
741
 
        InetAddress             bind_ip,
742
 
        int                             bind_port )
743
 
  
744
 
        throws Exception
745
 
  {
746
 
          Map reply = executeUDP( new HashMap(), bind_ip, bind_port );
747
 
          
748
 
          byte[] address = (byte[])reply.get( "source_ip_address" );
749
 
          
750
 
          return( InetAddress.getByName( new String( address )));
751
 
  }
752
 
  
753
 
  /**
754
 
   * Construct the default version check message.
755
 
   * @return message to send
756
 
   */
757
 
  private Map constructVersionCheckMessage( String reason ) {
758
 
    Map message = new HashMap();
759
 
    
760
 
    message.put( "appid", SystemProperties.getApplicationIdentifier());
761
 
    message.put( "version", Constants.AZUREUS_VERSION );
762
 
    
763
 
    String id = COConfigurationManager.getStringParameter( "ID", null );
764
 
    boolean send_info = COConfigurationManager.getBooleanParameter( "Send Version Info" );
765
 
    
766
 
    int last_send_time = COConfigurationManager.getIntParameter( "Send Version Info Last Time", -1 );
767
 
 
768
 
    int current_send_time = (int)(SystemTime.getCurrentTime()/1000);
769
 
    
770
 
    COConfigurationManager.setParameter( "Send Version Info Last Time", current_send_time );
771
 
    
772
 
    if( id != null && send_info ) {
773
 
        
774
 
      message.put( "id", id );
775
 
      message.put( "os", Constants.OSName );
776
 
      
777
 
      message.put( "os_version", System.getProperty( "os.version" ) );
778
 
      message.put( "os_arch", System.getProperty( "os.arch" ) );   //see http://lopica.sourceforge.net/os.html
779
 
    
780
 
      if ( last_send_time != -1 && last_send_time < current_send_time ){
781
 
          
782
 
                // tims since last
783
 
          
784
 
          message.put( "tsl", new Long(current_send_time-last_send_time));
785
 
      }
786
 
      
787
 
      message.put( "reason", reason );
788
 
      
789
 
      String  java_version = System.getProperty( "java.version" );
790
 
      if ( java_version == null ){  java_version = "unknown";  }
791
 
      message.put( "java", java_version );
792
 
      
793
 
      
794
 
      String  java_vendor = System.getProperty( "java.vm.vendor" );
795
 
      if ( java_vendor == null ){   java_vendor = "unknown";  }
796
 
      message.put( "javavendor", java_vendor );
797
 
      
798
 
      
799
 
      long  max_mem = Runtime.getRuntime().maxMemory()/(1024*1024);
800
 
      message.put( "javamx", new Long( max_mem ) );
801
 
      
802
 
      OverallStats      stats = StatsFactory.getStats();
803
 
      
804
 
      if ( stats != null ){
805
 
        
806
 
              //long total_bytes_downloaded     = stats.getDownloadedBytes();
807
 
              //long total_bytes_uploaded               = stats.getUploadedBytes();
808
 
              long total_uptime                         = stats.getTotalUpTime();
809
 
              
810
 
              //removed due to complaints about anonymous stats collection
811
 
              //message.put( "total_bytes_downloaded", new Long( total_bytes_downloaded ) );
812
 
              //message.put( "total_bytes_uploaded", new Long( total_bytes_uploaded ) );
813
 
              message.put( "total_uptime", new Long( total_uptime ) );
814
 
              //message.put( "dlstats", stats.getDownloadStats());
815
 
      }
816
 
      
817
 
      String    as = COConfigurationManager.getStringParameter( "ASN AS", null );
818
 
      
819
 
      if ( as != null ){
820
 
        
821
 
                // there was borkage with DNS based queries that left leading " on AS
822
 
          
823
 
          if ( as.startsWith( "\"" )){
824
 
                
825
 
                  as = as.substring( 1 ).trim();
826
 
                  
827
 
                  COConfigurationManager.setParameter( "ASN AS", as );
828
 
          }
829
 
          
830
 
          message.put( "ip_as", as );
831
 
      }
832
 
      
833
 
      String    asn = COConfigurationManager.getStringParameter( "ASN ASN", null );
834
 
      
835
 
      if ( asn != null ){
836
 
        
837
 
          if ( asn.length() > 64 ){
838
 
                  
839
 
                  asn = asn.substring( 0, 64 );
840
 
          }
841
 
          
842
 
          message.put( "ip_asn", asn );
843
 
      }
844
 
      
845
 
      String ui = COConfigurationManager.getStringParameter("ui");
846
 
      if (ui.length() > 0) {
847
 
        message.put("ui", ui);
848
 
      }
849
 
      
850
 
      if ( AzureusCoreFactory.isCoreAvailable()){
851
 
        
852
 
              //installed plugin IDs
853
 
              PluginInterface[] plugins = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaces();
854
 
              List pids = new ArrayList();
855
 
              for (int i=0;i<plugins.length;i++){
856
 
                String  pid = plugins[i].getPluginID();
857
 
                
858
 
                String  info = (String)plugins[i].getPluginconfig().getPluginStringParameter( "plugin.info" );
859
 
                
860
 
                  // filter out built-in and core ones
861
 
                if (    ( info != null && info.length() > 0 ) ||
862
 
                                (       !pid.startsWith( "<" ) && 
863
 
                                        !pid.startsWith( "azbp" ) &&
864
 
                                        !pid.startsWith( "azupdater" ) &&
865
 
                                        !pid.startsWith( "azplatform" ) &&
866
 
                                        !pids.contains( pid ))){
867
 
                
868
 
                        if ( info != null && info.length() > 0 ){
869
 
                                
870
 
                                if( info.length() < 256 ){
871
 
                                        
872
 
                                        pid += ":" + info;
873
 
                                        
874
 
                                }else{
875
 
                                        
876
 
                                        Debug.out( "Plugin '" + pid + "' reported excessive info string '" + info + "'" );
877
 
                                }
878
 
                        }
879
 
                        
880
 
                        pids.add( pid );
881
 
                }
882
 
              }
883
 
              message.put( "plugins", pids );
884
 
      }
885
 
    }
886
 
    
887
 
    
888
 
    //swt stuff
889
 
    try {
890
 
      Class c = Class.forName( "org.eclipse.swt.SWT" );
891
 
      
892
 
      String swt_platform = (String)c.getMethod( "getPlatform", new Class[]{} ).invoke( null, new Object[]{} );
893
 
      message.put( "swt_platform", swt_platform );
894
 
      
895
 
      if( send_info ) {
896
 
        Integer swt_version = (Integer)c.getMethod( "getVersion", new Class[]{} ).invoke( null, new Object[]{} );
897
 
        message.put( "swt_version", new Long( swt_version.longValue() ) );
898
 
 
899
 
        c = Class.forName("org.gudy.azureus2.ui.swt.mainwindow.MainWindow");
900
 
                                if (c != null) {
901
 
                                        c.getMethod("addToVersionCheckMessage", new Class[] { Map.class }).invoke(
902
 
                                                        null, new Object[] { message });
903
 
                                }
904
 
      }
905
 
    }
906
 
    catch( ClassNotFoundException e ) {  /* ignore */ }
907
 
    catch( NoClassDefFoundError er ) {  /* ignore */ }
908
 
    catch( InvocationTargetException err ) {  /* ignore */ }
909
 
    catch( Throwable t ) {  t.printStackTrace();  }
910
 
    
911
 
    
912
 
    boolean using_phe = COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" );
913
 
    message.put( "using_phe", using_phe ? new Long(1) : new Long(0) );
914
 
    
915
 
    return message;
916
 
  }
917
 
  
918
 
  public static void
919
 
  main(
920
 
        String[]        args )
921
 
  {
922
 
          try{
923
 
                  COConfigurationManager.initialise();
924
 
                  
925
 
                  System.out.println( "UDP:  " + getSingleton().getExternalIpAddressUDP(null,0));
926
 
                  System.out.println( "TCP:  " + getSingleton().getExternalIpAddressTCP(null,0));
927
 
                  System.out.println( "HTTP: " + getSingleton().getExternalIpAddressHTTP());
928
 
                  
929
 
          }catch( Throwable e){
930
 
                  e.printStackTrace();
931
 
          }
932
 
  }
933
 
}
 
1
/*
 
2
 * Created on Dec 20, 2004
 
3
 * Created by Alon Rohter
 
4
 * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
17
 * 
 
18
 * AELITIS, SAS au capital de 46,603.30 euros
 
19
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
 
20
 *
 
21
 */
 
22
 
 
23
package com.aelitis.azureus.core.versioncheck;
 
24
 
 
25
 
 
26
import java.io.BufferedInputStream;
 
27
import java.io.ByteArrayInputStream;
 
28
import java.io.ByteArrayOutputStream;
 
29
import java.io.IOException;
 
30
import java.io.InputStream;
 
31
import java.io.OutputStream;
 
32
import java.lang.reflect.InvocationTargetException;
 
33
import java.net.*;
 
34
import java.util.*;
 
35
 
 
36
import org.gudy.azureus2.core3.config.COConfigurationManager;
 
37
import org.gudy.azureus2.core3.config.ParameterListener;
 
38
import org.gudy.azureus2.core3.internat.MessageText;
 
39
import org.gudy.azureus2.core3.logging.*;
 
40
import org.gudy.azureus2.core3.stats.transfer.*;
 
41
import org.gudy.azureus2.core3.util.*;
 
42
 
 
43
import org.gudy.azureus2.plugins.PluginInterface;
 
44
 
 
45
import com.aelitis.azureus.core.AzureusCoreFactory;
 
46
import com.aelitis.azureus.core.clientmessageservice.*;
 
47
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
 
48
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN;
 
49
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
 
50
import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
 
51
import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler;
 
52
 
 
53
 
 
54
 
 
55
/**
 
56
 * Client for checking version information from a remote server.
 
57
 */
 
58
public class VersionCheckClient {
 
59
        private static final LogIDs LOGID = LogIDs.CORE;
 
60
        
 
61
        public static final String      REASON_UPDATE_CHECK_START               = "us";
 
62
        public static final String      REASON_UPDATE_CHECK_PERIODIC    = "up";
 
63
        public static final String      REASON_CHECK_SWT                                = "sw";
 
64
        public static final String      REASON_DHT_EXTENDED_ALLOWED             = "dx";
 
65
        public static final String      REASON_DHT_ENABLE_ALLOWED               = "de";
 
66
        public static final String      REASON_EXTERNAL_IP                              = "ip";
 
67
        public static final String      REASON_RECOMMENDED_PLUGINS              = "rp";
 
68
        public static final String      REASON_SECONDARY_CHECK                  = "sc";
 
69
        
 
70
 
 
71
  private static final String   AZ_MSG_SERVER_ADDRESS_V4        = Constants.VERSION_SERVER_V4;
 
72
  private static final int              AZ_MSG_SERVER_PORT                      = 27001;
 
73
  private static final String   MESSAGE_TYPE_ID                         = "AZVER";
 
74
  
 
75
  public static final String    HTTP_SERVER_ADDRESS_V4          = AZ_MSG_SERVER_ADDRESS_V4;
 
76
  public static final int               HTTP_SERVER_PORT                        = 80;
 
77
 
 
78
  public static final String    TCP_SERVER_ADDRESS_V4           = AZ_MSG_SERVER_ADDRESS_V4;
 
79
  public static final int               TCP_SERVER_PORT                         = 80;
 
80
 
 
81
  public static final String    UDP_SERVER_ADDRESS_V4           = AZ_MSG_SERVER_ADDRESS_V4;
 
82
  public static final int               UDP_SERVER_PORT                         = 2080;
 
83
 
 
84
  public static final String    AZ_MSG_SERVER_ADDRESS_V6        = Constants.VERSION_SERVER_V6;
 
85
  public static final String    HTTP_SERVER_ADDRESS_V6          = AZ_MSG_SERVER_ADDRESS_V6;
 
86
  public static final String    TCP_SERVER_ADDRESS_V6           = AZ_MSG_SERVER_ADDRESS_V6;
 
87
  public static final String    UDP_SERVER_ADDRESS_V6           = AZ_MSG_SERVER_ADDRESS_V6;
 
88
  
 
89
  
 
90
  private static final long             CACHE_PERIOD    = 5*60*1000;
 
91
  private static boolean secondary_check_done;
 
92
  
 
93
  
 
94
  static{
 
95
          VersionCheckClientUDPCodecs.registerCodecs();
 
96
  }
 
97
  
 
98
  private static boolean        prefer_v6;
 
99
  
 
100
  static{
 
101
          
 
102
          COConfigurationManager.addAndFireParameterListener(
 
103
                          "IPV6 Prefer Addresses",
 
104
                          new ParameterListener()
 
105
                          {
 
106
                                 public void 
 
107
                                 parameterChanged(
 
108
                                        String  name )
 
109
                                 {
 
110
                                         prefer_v6 = COConfigurationManager.getBooleanParameter( name );
 
111
                                 } 
 
112
                          });
 
113
  }
 
114
  
 
115
  private static final int      AT_V4           = 1;
 
116
  private static final int      AT_V6           = 2;
 
117
  private static final int      AT_EITHER       = 3;
 
118
  
 
119
  private static final VersionCheckClient instance = new VersionCheckClient();
 
120
  
 
121
  private Map last_check_data_v4 = null;
 
122
  private Map last_check_data_v6 = null;
 
123
  
 
124
  private final AEMonitor check_mon = new AEMonitor( "versioncheckclient" );
 
125
  
 
126
  private long last_check_time_v4 = 0; 
 
127
  private long last_check_time_v6 = 0; 
 
128
  
 
129
  
 
130
  private VersionCheckClient() {
 
131
    /* blank */
 
132
  }
 
133
  
 
134
  
 
135
  
 
136
  /**
 
137
   * Get the singleton instance of the version check client.
 
138
   * @return version check client
 
139
   */
 
140
  public static VersionCheckClient getSingleton() {  return instance;  }
 
141
  
 
142
  
 
143
  
 
144
  /**
 
145
   * Get the version check reply info.
 
146
   * @return reply data, possibly cached, if the server was already checked within the last minute
 
147
   */
 
148
  
 
149
  public Map 
 
150
  getVersionCheckInfo( 
 
151
        String  reason )
 
152
  {
 
153
          return( getVersionCheckInfo( reason, AT_EITHER ));
 
154
  }
 
155
  
 
156
  public Map 
 
157
  getVersionCheckInfo( 
 
158
        String  reason,
 
159
        int             address_type )
 
160
  {
 
161
          if ( address_type == AT_V4 ){
 
162
                  
 
163
                  return( getVersionCheckInfoSupport( reason, false, false, false ));
 
164
 
 
165
          }else if ( address_type == AT_V6 ){
 
166
                  
 
167
                  return( getVersionCheckInfoSupport( reason, false, false, true ));
 
168
 
 
169
          }else{
 
170
                  
 
171
                  Map   reply = getVersionCheckInfoSupport( reason, false, false, prefer_v6 );
 
172
                  
 
173
                  if ( reply == null || reply.size() == 0 ){
 
174
                          
 
175
                          reply =  getVersionCheckInfoSupport( reason, false, false, !prefer_v6 );
 
176
                  }
 
177
                  
 
178
                  return( reply );
 
179
          }
 
180
  }
 
181
 
 
182
 
 
183
  protected Map 
 
184
  getVersionCheckInfoSupport( 
 
185
          String        reason, 
 
186
          boolean       only_if_cached, 
 
187
          boolean       force,
 
188
          boolean       v6 )
 
189
  {
 
190
        if ( v6 ){
 
191
 
 
192
            try {  check_mon.enter();
 
193
            
 
194
              long time_diff = SystemTime.getCurrentTime() - last_check_time_v6;
 
195
             
 
196
              force = force || time_diff > CACHE_PERIOD || time_diff < 0;
 
197
              
 
198
              if( last_check_data_v6 == null || last_check_data_v6.size() == 0 || force ) {
 
199
                  // if we've never checked before then we go ahead even if the "only_if_cached"
 
200
                  // flag is set as its had not chance of being cached yet!
 
201
                if ( only_if_cached && last_check_data_v6 != null ){
 
202
                        return( new HashMap() );
 
203
                }
 
204
                try {
 
205
                  last_check_data_v6 = performVersionCheck( constructVersionCheckMessage( reason ), true, true, true );
 
206
                }
 
207
                catch( UnknownHostException t ) {
 
208
                        // no internet
 
209
                        Debug.out(t.getClass().getName() + ": " + t.getMessage());
 
210
                }
 
211
                catch( Throwable t ) {
 
212
                        Debug.out(t);
 
213
                  last_check_data_v6 = new HashMap();
 
214
                }
 
215
              }
 
216
              else {
 
217
                Logger.log(new LogEvent(LOGID, "VersionCheckClient is using "
 
218
                                                        + "cached version check info. Using " + last_check_data_v6.size()
 
219
                                                        + " reply keys.")); 
 
220
              }
 
221
            }
 
222
            finally {  check_mon.exit();  }
 
223
            
 
224
            if( last_check_data_v6 == null )  last_check_data_v6 = new HashMap();
 
225
            
 
226
            return last_check_data_v6;
 
227
            
 
228
        }else{
 
229
                
 
230
           try {  check_mon.enter();
 
231
            
 
232
              long time_diff = SystemTime.getCurrentTime() - last_check_time_v4;
 
233
             
 
234
              force = force || time_diff > CACHE_PERIOD || time_diff < 0;
 
235
              
 
236
              if( last_check_data_v4 == null || last_check_data_v4.size() == 0 || force ) {
 
237
                  // if we've never checked before then we go ahead even if the "only_if_cached"
 
238
                  // flag is set as its had not chance of being cached yet!
 
239
                if ( only_if_cached && last_check_data_v4 != null ){
 
240
                        return( new HashMap() );
 
241
                }
 
242
                try {
 
243
                  last_check_data_v4 = performVersionCheck( constructVersionCheckMessage( reason ), true, true, false );
 
244
                }
 
245
                catch( UnknownHostException t ) {
 
246
                        // no internet
 
247
                        Debug.outNoStack("VersionCheckClient - " + t.getClass().getName() + ": " + t.getMessage());
 
248
                }
 
249
                catch (IOException t) {
 
250
                        // General connection problem.
 
251
                        Debug.outNoStack("VersionCheckClient - " + t.getClass().getName() + ": " + t.getMessage());
 
252
                }
 
253
                catch( Throwable t ) {
 
254
                        Debug.out(t);
 
255
                  last_check_data_v4 = new HashMap();
 
256
                }
 
257
              }
 
258
              else {
 
259
                  if (Logger.isEnabled())
 
260
                          Logger.log(new LogEvent(LOGID, "VersionCheckClient is using "
 
261
                                                        + "cached version check info. Using " + last_check_data_v4.size()
 
262
                                                        + " reply keys.")); 
 
263
              }
 
264
            }
 
265
            finally {  check_mon.exit();  }
 
266
            
 
267
            if( last_check_data_v4 == null )  last_check_data_v4 = new HashMap();
 
268
            
 
269
            return last_check_data_v4;
 
270
        }
 
271
  }
 
272
  
 
273
  private boolean
 
274
  isVersionCheckDataValid(
 
275
        int             address_type )
 
276
  {     
 
277
          boolean v6_ok = last_check_data_v6 != null && last_check_data_v6.size() > 0;
 
278
          boolean v4_ok = last_check_data_v4 != null && last_check_data_v4.size() > 0;
 
279
 
 
280
          if ( address_type == AT_V4 ){
 
281
                  
 
282
                  return( v4_ok );
 
283
                  
 
284
          }else if ( address_type == AT_V6 ){
 
285
                  
 
286
                  return( v6_ok );
 
287
                  
 
288
          }else{
 
289
                  
 
290
                  return( v4_ok | v6_ok );
 
291
          }
 
292
  }
 
293
  
 
294
  public long
 
295
  getCacheTime(
 
296
                  boolean v6 )
 
297
  {
 
298
          return( v6?last_check_time_v6:last_check_time_v4);
 
299
  }
 
300
  
 
301
  /**
 
302
   * Get the ip address seen by the version check server.
 
303
   * NOTE: This information may be cached, see getVersionCheckInfo().
 
304
   * @return external ip address, or empty string if no address information found
 
305
   */
 
306
  
 
307
  public String 
 
308
  getExternalIpAddress(
 
309
          boolean       only_if_cached,
 
310
          boolean       v6 )
 
311
  {
 
312
    Map reply = getVersionCheckInfoSupport( REASON_EXTERNAL_IP, only_if_cached, false, v6 );
 
313
    
 
314
    byte[] address = (byte[])reply.get( "source_ip_address" );
 
315
    if( address != null ) {
 
316
      return new String( address );
 
317
    }
 
318
    
 
319
    return( null );
 
320
  }
 
321
  
 
322
  
 
323
  /**
 
324
   * Is the DHT plugin allowed to be enabled.
 
325
   * @return true if DHT can be enabled, false if it should not be enabled
 
326
   */
 
327
  public boolean DHTEnableAllowed() {
 
328
    Map reply = getVersionCheckInfo( REASON_DHT_ENABLE_ALLOWED, AT_EITHER );
 
329
    
 
330
    boolean     res = false;
 
331
    
 
332
    byte[] value = (byte[])reply.get( "enable_dht" );
 
333
    
 
334
    if( value != null ) {
 
335
        
 
336
      res = new String( value ).equalsIgnoreCase( "true" );
 
337
    }
 
338
    
 
339
        // we take the view that if the version check failed then we go ahead
 
340
        // and enable the DHT (i.e. we're being optimistic)
 
341
 
 
342
    if ( !res ){
 
343
        res = !isVersionCheckDataValid( AT_EITHER );
 
344
    }
 
345
    
 
346
    return res;
 
347
  }
 
348
  
 
349
  
 
350
  /**
 
351
   * Is the DHT allowed to be used by external plugins.
 
352
   * @return true if extended DHT use is allowed, false if not allowed
 
353
   */
 
354
  public boolean DHTExtendedUseAllowed() {
 
355
    Map reply = getVersionCheckInfo( REASON_DHT_EXTENDED_ALLOWED, AT_EITHER );
 
356
    
 
357
    boolean     res = false;
 
358
    
 
359
    byte[] value = (byte[])reply.get( "enable_dht_extended_use" );
 
360
    if( value != null ) {
 
361
      res = new String( value ).equalsIgnoreCase( "true" );
 
362
    }
 
363
    
 
364
        // be generous and enable extended use if check failed
 
365
    
 
366
    if ( !res ){
 
367
        res = !isVersionCheckDataValid( AT_EITHER );
 
368
    }
 
369
    
 
370
    return res;
 
371
  }
 
372
  
 
373
  public String[]
 
374
  getRecommendedPlugins()
 
375
  {
 
376
          Map reply = getVersionCheckInfo( REASON_RECOMMENDED_PLUGINS, AT_EITHER );
 
377
 
 
378
          List  l = (List)reply.get( "recommended_plugins" );
 
379
          
 
380
          if ( l == null ){
 
381
                  
 
382
                  return( new String[0] );
 
383
          }
 
384
          
 
385
          String[]      res = new String[l.size()];
 
386
          
 
387
          for (int i=0;i<l.size();i++){
 
388
                  
 
389
                  res[i] = new String((byte[])l.get(i));
 
390
          }
 
391
          
 
392
          return( res );
 
393
  }
 
394
  
 
395
  /**
 
396
   * Perform the actual version check by connecting to the version server.
 
397
   * @param data_to_send version message
 
398
   * @return version reply
 
399
   * @throws Exception if the server check connection fails
 
400
   */
 
401
  private Map 
 
402
  performVersionCheck( 
 
403
        Map     data_to_send,
 
404
        boolean use_az_message,
 
405
        boolean use_http,
 
406
        boolean v6 )
 
407
  
 
408
        throws Exception 
 
409
  {
 
410
        Exception       error   = null;
 
411
        Map                     reply   = null;
 
412
        
 
413
        if ( use_az_message ){
 
414
        
 
415
                try{
 
416
                        reply = executeAZMessage( data_to_send, v6 );
 
417
                        
 
418
                        reply.put( "protocol_used", "AZMSG" );
 
419
                }
 
420
                catch (IOException e) {
 
421
                        error = e;
 
422
                }
 
423
                catch (Exception e) {
 
424
                        Debug.printStackTrace( e );
 
425
                        error = e;
 
426
                }
 
427
        }
 
428
        
 
429
        if ( reply == null && use_http ){
 
430
                
 
431
                try{
 
432
                        reply = executeHTTP( data_to_send, v6 );
 
433
                        
 
434
                        reply.put( "protocol_used", "HTTP" );
 
435
                        
 
436
                        error = null;
 
437
                }
 
438
                catch (IOException e) {
 
439
                        error = e;
 
440
                }
 
441
                catch (Exception e){
 
442
                        Debug.printStackTrace(e);
 
443
                        error = e;
 
444
                        
 
445
                }
 
446
        }
 
447
        if ( error != null ){
 
448
                
 
449
                throw( error );
 
450
        }
 
451
      
 
452
        if (Logger.isEnabled())
 
453
                                Logger.log(new LogEvent(LOGID, "VersionCheckClient server "
 
454
                                                + "version check successful. Received " + reply.size()
 
455
                                                + " reply keys."));
 
456
 
 
457
        if ( v6 ){
 
458
        
 
459
                last_check_time_v6 = SystemTime.getCurrentTime();
 
460
                
 
461
        }else{
 
462
                
 
463
                last_check_time_v4 = SystemTime.getCurrentTime();
 
464
        }
 
465
        
 
466
    return reply;
 
467
  }
 
468
  
 
469
  private Map
 
470
  executeAZMessage(
 
471
        Map             data_to_send,
 
472
        boolean v6 )
 
473
  
 
474
        throws Exception
 
475
  {
 
476
          String        host = v6?AZ_MSG_SERVER_ADDRESS_V6:AZ_MSG_SERVER_ADDRESS_V4;
 
477
          
 
478
          if (Logger.isEnabled())
 
479
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
 
480
                                  + "version information from " + host + ":" + AZ_MSG_SERVER_PORT)); 
 
481
 
 
482
          ClientMessageService  msg_service = null;
 
483
          Map                                   reply           = null; 
 
484
 
 
485
          try{
 
486
                  msg_service = ClientMessageServiceClient.getServerService( host, AZ_MSG_SERVER_PORT, MESSAGE_TYPE_ID );
 
487
 
 
488
                  msg_service.sendMessage( data_to_send );  //send our version message
 
489
 
 
490
                  reply = msg_service.receiveMessage();  //get the server reply
 
491
 
 
492
                  preProcessReply( reply, v6 );
 
493
                  
 
494
          }finally{
 
495
 
 
496
                  if ( msg_service != null ){
 
497
 
 
498
                          msg_service.close();
 
499
                  }
 
500
          }
 
501
          
 
502
          return( reply );
 
503
  }
 
504
  
 
505
  private Map
 
506
  executeHTTP(
 
507
        Map             data_to_send,
 
508
        boolean v6 )
 
509
  
 
510
        throws Exception
 
511
  {
 
512
          String        host = v6?HTTP_SERVER_ADDRESS_V6:HTTP_SERVER_ADDRESS_V4;
 
513
 
 
514
          if (Logger.isEnabled())
 
515
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
 
516
                                  + "version information from " + host + ":" + HTTP_SERVER_PORT + " via HTTP" )); 
 
517
 
 
518
          String        url_str = "http://" + host + (HTTP_SERVER_PORT==80?"":(":" + HTTP_SERVER_PORT)) + "/version?";
 
519
 
 
520
          url_str += URLEncoder.encode( new String( BEncoder.encode( data_to_send ), "ISO-8859-1" ), "ISO-8859-1" );
 
521
          
 
522
          URL   url = new URL( url_str );
 
523
          
 
524
          HttpURLConnection     url_connection = (HttpURLConnection)url.openConnection();
 
525
          
 
526
          url_connection.connect();
 
527
          
 
528
          try{
 
529
                  InputStream   is = url_connection.getInputStream();
 
530
                  
 
531
                  Map   reply = BDecoder.decode( new BufferedInputStream( is ));
 
532
                  
 
533
                  preProcessReply( reply, v6 );
 
534
 
 
535
                  return( reply );
 
536
                  
 
537
          }finally{
 
538
                  
 
539
                  url_connection.disconnect();
 
540
          }
 
541
  }
 
542
  
 
543
  public String
 
544
  getHTTPGetString(
 
545
        boolean for_proxy,
 
546
        boolean v6 )
 
547
  {
 
548
          return( getHTTPGetString( new HashMap(), for_proxy, v6 ));
 
549
  }
 
550
  
 
551
  private String
 
552
  getHTTPGetString(
 
553
        Map             content,
 
554
        boolean for_proxy,
 
555
        boolean v6 )
 
556
  {
 
557
          String        host = v6?HTTP_SERVER_ADDRESS_V6:HTTP_SERVER_ADDRESS_V4;
 
558
 
 
559
          String        get_str = "GET " + (for_proxy?("http://" + host + ":" + HTTP_SERVER_PORT ):"") +"/version?";
 
560
 
 
561
          try{
 
562
                  get_str += URLEncoder.encode( new String( BEncoder.encode( content ), "ISO-8859-1" ), "ISO-8859-1" );
 
563
                  
 
564
          }catch( Throwable e ){ 
 
565
          }
 
566
          
 
567
          get_str +=" HTTP/1.1" + "\015\012" + "\015\012";
 
568
         
 
569
          return( get_str );
 
570
  }
 
571
  
 
572
  private Map
 
573
  executeTCP(
 
574
        Map                             data_to_send,
 
575
        InetAddress             bind_ip,
 
576
        int                             bind_port,
 
577
        boolean                 v6 )
 
578
  
 
579
        throws Exception
 
580
  {
 
581
          String        host = v6?TCP_SERVER_ADDRESS_V6:TCP_SERVER_ADDRESS_V4;
 
582
 
 
583
          if (Logger.isEnabled())
 
584
                  Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
 
585
                                  + "version information from " + host + ":" + TCP_SERVER_PORT + " via TCP" )); 
 
586
 
 
587
          String        get_str = getHTTPGetString( data_to_send, false, v6 );
 
588
          
 
589
          Socket        socket = null;
 
590
          
 
591
          try{
 
592
                  socket = new Socket();
 
593
                 
 
594
                  if ( bind_ip != null ){
 
595
                          
 
596
                          socket.bind( new InetSocketAddress( bind_ip, bind_port ));
 
597
                          
 
598
                  }else if ( bind_port != 0 ){
 
599
                          
 
600
                          socket.bind( new InetSocketAddress( bind_port ));
 
601
                  }
 
602
                  
 
603
                  socket.setSoTimeout( 10000 );
 
604
                
 
605
                  socket.connect( new InetSocketAddress( host, TCP_SERVER_PORT ), 10000 );
 
606
                  
 
607
                  OutputStream  os = socket.getOutputStream();
 
608
                  
 
609
                  os.write( get_str.getBytes( "ISO-8859-1" ));
 
610
                  
 
611
                  os.flush();
 
612
                  
 
613
                  InputStream   is = socket.getInputStream();
 
614
                  
 
615
                  ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
616
                                
 
617
                  byte[]        buffer = new byte[1024];
 
618
 
 
619
                  int   total_len = 0;
 
620
                  
 
621
                  while( true ){
 
622
                          
 
623
                          int   len = is.read( buffer );
 
624
                          
 
625
                          if ( len <= 0 ){
 
626
                                  
 
627
                                  break;
 
628
                          }
 
629
                          
 
630
                          total_len += len;
 
631
                          
 
632
                          if ( total_len > 16000 ){
 
633
                                  
 
634
                                  throw( new IOException( "reply too large" ));
 
635
                          }
 
636
                          
 
637
                          baos.write( buffer, 0, len );
 
638
                  }
 
639
                  
 
640
                  byte[]        reply_bytes = baos.toByteArray();
 
641
                  
 
642
                  for (int i=3;i<reply_bytes.length;i++){
 
643
                          
 
644
                          if (          reply_bytes[i-3]== (byte)'\015' &&
 
645
                                                reply_bytes[i-2]== (byte)'\012' &&
 
646
                                                reply_bytes[i-1]== (byte)'\015' &&
 
647
                                                reply_bytes[i-0]== (byte)'\012' ){
 
648
                                          
 
649
                                  Map reply = BDecoder.decode( new BufferedInputStream( new ByteArrayInputStream( reply_bytes, i+1, reply_bytes.length - (i+1 ))));
 
650
                                  
 
651
                                  preProcessReply( reply, v6 );
 
652
 
 
653
                                  return( reply );
 
654
                          }
 
655
                  }
 
656
                  
 
657
                  throw( new Exception( "Invalid reply: " + new String( reply_bytes )));
 
658
                  
 
659
          }finally{
 
660
                  
 
661
                  if ( socket != null ){
 
662
                          
 
663
                          try{
 
664
                                  socket.close();
 
665
                                  
 
666
                          }catch( Throwable e ){
 
667
                                  
 
668
                          }
 
669
                  }
 
670
          }
 
671
  }
 
672
  
 
673
  private Map
 
674
  executeUDP(
 
675
        Map                             data_to_send,
 
676
        InetAddress             bind_ip,
 
677
        int                             bind_port,
 
678
        boolean                 v6 )
 
679
  
 
680
        throws Exception
 
681
  {
 
682
          String        host = v6?UDP_SERVER_ADDRESS_V6:UDP_SERVER_ADDRESS_V4;
 
683
 
 
684
          PRUDPReleasablePacketHandler handler = PRUDPPacketHandlerFactory.getReleasableHandler( bind_port );
 
685
                  
 
686
          PRUDPPacketHandler    packet_handler = handler.getHandler();
 
687
          
 
688
          long timeout = 5;
 
689
          
 
690
          Random random = new Random();
 
691
          
 
692
          try{
 
693
                  Exception     last_error = null;
 
694
                  
 
695
                  packet_handler.setExplicitBindAddress( bind_ip );       
 
696
                  
 
697
                  for (int i=0;i<3;i++){
 
698
                          
 
699
                          try{
 
700
                                        // connection ids for requests must always have their msb set...
 
701
                                        // apart from the original darn udp tracker spec....
 
702
                                  
 
703
                                  long connection_id = 0x8000000000000000L | random.nextLong();
 
704
                                  
 
705
                                  VersionCheckClientUDPRequest  request_packet = new VersionCheckClientUDPRequest( connection_id );
 
706
                                  
 
707
                                  request_packet.setPayload( data_to_send );
 
708
                                  
 
709
                                  VersionCheckClientUDPReply reply_packet = (VersionCheckClientUDPReply)packet_handler.sendAndReceive( null, request_packet, new InetSocketAddress( host, UDP_SERVER_PORT ), timeout );
 
710
                
 
711
                                  Map   reply = reply_packet.getPayload();
 
712
                                  
 
713
                                  preProcessReply( reply, v6 );
 
714
                                  
 
715
                                  return( reply );
 
716
                                  
 
717
                          }catch( Exception e){
 
718
                                  
 
719
                                  last_error    = e;
 
720
                                  
 
721
                                  timeout = timeout * 2;
 
722
                          }
 
723
                  }
 
724
                  
 
725
                  if ( last_error != null ){
 
726
                          
 
727
                          throw( last_error );
 
728
                  }
 
729
                  
 
730
                  throw( new Exception( "Timeout" ));
 
731
                  
 
732
          }finally{
 
733
                 
 
734
                  packet_handler.setExplicitBindAddress( null );
 
735
 
 
736
                  handler.release();
 
737
          }
 
738
  }
 
739
  
 
740
  protected void
 
741
  preProcessReply(
 
742
        Map                                     reply,
 
743
        final boolean           v6 )
 
744
  {
 
745
          NetworkAdmin admin = NetworkAdmin.getSingleton();
 
746
          
 
747
          try{
 
748
                  byte[] address = (byte[])reply.get( "source_ip_address" );
 
749
 
 
750
                  InetAddress my_ip = InetAddress.getByName( new String( address ));
 
751
                  
 
752
                  NetworkAdminASN old_asn = admin.getCurrentASN();
 
753
                          
 
754
                  NetworkAdminASN new_asn = admin.lookupASN( my_ip );
 
755
 
 
756
                  if ( !new_asn.sameAs( old_asn )){
 
757
 
 
758
                          // kick off a secondary version check to communicate the new information
 
759
 
 
760
                          if ( !secondary_check_done ){
 
761
 
 
762
                                  secondary_check_done  = true;
 
763
 
 
764
                                  new AEThread( "Secondary version check", true )
 
765
                                  {
 
766
                                          public void
 
767
                                          runSupport()
 
768
                                          {
 
769
                                                  getVersionCheckInfoSupport( REASON_SECONDARY_CHECK, false, true, v6 );
 
770
                                          }
 
771
                                  }.start();
 
772
                          }
 
773
                  }
 
774
         }catch( Throwable e ){
 
775
                         
 
776
                 Debug.printStackTrace(e);
 
777
         }
 
778
         
 
779
         Long   as_advice = (Long)reply.get( "as_advice" );
 
780
         
 
781
         if ( as_advice != null ){
 
782
                 
 
783
                 NetworkAdminASN current_asn = admin.getCurrentASN();
 
784
 
 
785
             String     asn = current_asn.getASName();
 
786
 
 
787
             if ( asn != null ){
 
788
                
 
789
                         long   advice = as_advice.longValue();
 
790
                         
 
791
                         if ( advice != 0 ){
 
792
                        
 
793
                                        // require crypto
 
794
                                 
 
795
                                 String done_asn = COConfigurationManager.getStringParameter( "ASN Advice Followed", "" );
 
796
                                 
 
797
                                 if ( !done_asn.equals( asn )){
 
798
                                         
 
799
                                         COConfigurationManager.setParameter( "ASN Advice Followed", asn );
 
800
                                         
 
801
                                         boolean        change  = advice == 1 || advice == 2;
 
802
                                         boolean        alert   = advice == 1 || advice == 3;
 
803
                                         
 
804
                                         if ( !COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" )){
 
805
                                                 
 
806
                                                 if ( change ){
 
807
                                                         
 
808
                                                         COConfigurationManager.setParameter( "network.transport.encrypted.require", true );
 
809
                                                 }
 
810
                                                 
 
811
                                                 if ( alert ){
 
812
                                                         
 
813
                                                         String msg = 
 
814
                                                                 MessageText.getString(
 
815
                                                                                "crypto.alert.as.warning",
 
816
                                                                                new String[]{ asn });
 
817
                                                         
 
818
                                                         Logger.log( new LogAlert( false, LogAlert.AT_WARNING, msg ));
 
819
                                                 }
 
820
                                         }
 
821
                                 }
 
822
                         }
 
823
             }
 
824
         }
 
825
         
 
826
                // set ui.toolbar.uiswitcher based on instructions from tracker
 
827
                // Really shouldn't be in VersionCheck client, but instead have some 
 
828
                // listener and have the code elsewhere.  Simply calling 
 
829
                //getVersionCheckInfo from "code elsewhere" (to get the cached result) 
 
830
                //caused a deadlock at startup.
 
831
                Long lEnabledUISwitcher = (Long) reply.get("ui.toolbar.uiswitcher");
 
832
                if (lEnabledUISwitcher != null) {
 
833
                        COConfigurationManager.setBooleanDefault("ui.toolbar.uiswitcher",
 
834
                                        lEnabledUISwitcher.longValue() == 1);
 
835
                }
 
836
  }
 
837
  
 
838
  public InetAddress
 
839
  getExternalIpAddressHTTP(
 
840
        boolean         v6 )
 
841
  
 
842
        throws Exception
 
843
  {
 
844
          Map reply = executeHTTP( new HashMap(), v6 );
 
845
          
 
846
          byte[] address = (byte[])reply.get( "source_ip_address" );
 
847
          
 
848
          return( InetAddress.getByName( new String( address )));
 
849
  }
 
850
  
 
851
  public InetAddress
 
852
  getExternalIpAddressTCP(
 
853
        InetAddress             bind_ip,
 
854
        int                             bind_port,
 
855
        boolean                 v6 )
 
856
  
 
857
        throws Exception
 
858
  {
 
859
          Map reply = executeTCP( new HashMap(), bind_ip, bind_port, v6 );
 
860
          
 
861
          byte[] address = (byte[])reply.get( "source_ip_address" );
 
862
          
 
863
          return( InetAddress.getByName( new String( address )));
 
864
  }
 
865
  
 
866
  public InetAddress
 
867
  getExternalIpAddressUDP(
 
868
        InetAddress             bind_ip,
 
869
        int                             bind_port,
 
870
        boolean                 v6 )
 
871
  
 
872
        throws Exception
 
873
  {
 
874
          Map reply = executeUDP( new HashMap(), bind_ip, bind_port, v6 );
 
875
          
 
876
          byte[] address = (byte[])reply.get( "source_ip_address" );
 
877
          
 
878
          return( InetAddress.getByName( new String( address )));
 
879
  }
 
880
  
 
881
  /**
 
882
   * Construct the default version check message.
 
883
   * @return message to send
 
884
   */
 
885
  private Map constructVersionCheckMessage( String reason ) {
 
886
    Map message = new HashMap();
 
887
    
 
888
    message.put( "appid", SystemProperties.getApplicationIdentifier());
 
889
    message.put( "version", Constants.AZUREUS_VERSION );
 
890
    
 
891
    String id = COConfigurationManager.getStringParameter( "ID", null );
 
892
    boolean send_info = COConfigurationManager.getBooleanParameter( "Send Version Info" );
 
893
    
 
894
    int last_send_time = COConfigurationManager.getIntParameter( "Send Version Info Last Time", -1 );
 
895
 
 
896
    int current_send_time = (int)(SystemTime.getCurrentTime()/1000);
 
897
    
 
898
    COConfigurationManager.setParameter( "Send Version Info Last Time", current_send_time );
 
899
    
 
900
    if( id != null && send_info ) {
 
901
        
 
902
      message.put( "id", id );
 
903
      message.put( "os", Constants.OSName );
 
904
      
 
905
      message.put( "os_version", System.getProperty( "os.version" ) );
 
906
      message.put( "os_arch", System.getProperty( "os.arch" ) );   //see http://lopica.sourceforge.net/os.html
 
907
    
 
908
      if ( last_send_time != -1 && last_send_time < current_send_time ){
 
909
          
 
910
                // tims since last
 
911
          
 
912
          message.put( "tsl", new Long(current_send_time-last_send_time));
 
913
      }
 
914
      
 
915
      message.put( "reason", reason );
 
916
      
 
917
      String  java_version = System.getProperty( "java.version" );
 
918
      if ( java_version == null ){  java_version = "unknown";  }
 
919
      message.put( "java", java_version );
 
920
      
 
921
      
 
922
      String  java_vendor = System.getProperty( "java.vm.vendor" );
 
923
      if ( java_vendor == null ){   java_vendor = "unknown";  }
 
924
      message.put( "javavendor", java_vendor );
 
925
      
 
926
      
 
927
      long  max_mem = Runtime.getRuntime().maxMemory()/(1024*1024);
 
928
      message.put( "javamx", new Long( max_mem ) );
 
929
      
 
930
      String java_rt_name = System.getProperty("java.runtime.name");
 
931
      if (java_rt_name != null) {
 
932
        message.put( "java_rt_name", java_rt_name);
 
933
      }
 
934
 
 
935
      String java_rt_version = System.getProperty("java.runtime.version");
 
936
      if (java_rt_version != null) {
 
937
        message.put( "java_rt_version", java_rt_version);
 
938
      }
 
939
 
 
940
      OverallStats      stats = StatsFactory.getStats();
 
941
      
 
942
      if ( stats != null ){
 
943
        
 
944
              //long total_bytes_downloaded     = stats.getDownloadedBytes();
 
945
              //long total_bytes_uploaded               = stats.getUploadedBytes();
 
946
              long total_uptime                         = stats.getTotalUpTime();
 
947
              
 
948
              //removed due to complaints about anonymous stats collection
 
949
              //message.put( "total_bytes_downloaded", new Long( total_bytes_downloaded ) );
 
950
              //message.put( "total_bytes_uploaded", new Long( total_bytes_uploaded ) );
 
951
              message.put( "total_uptime", new Long( total_uptime ) );
 
952
              //message.put( "dlstats", stats.getDownloadStats());
 
953
      }
 
954
      
 
955
      String    as = COConfigurationManager.getStringParameter( "ASN AS", null );
 
956
      
 
957
      if ( as != null ){
 
958
        
 
959
                // there was borkage with DNS based queries that left leading " on AS
 
960
          
 
961
          if ( as.startsWith( "\"" )){
 
962
                
 
963
                  as = as.substring( 1 ).trim();
 
964
                  
 
965
                  COConfigurationManager.setParameter( "ASN AS", as );
 
966
          }
 
967
          
 
968
          message.put( "ip_as", as );
 
969
      }
 
970
      
 
971
      String    asn = COConfigurationManager.getStringParameter( "ASN ASN", null );
 
972
      
 
973
      if ( asn != null ){
 
974
        
 
975
          if ( asn.length() > 64 ){
 
976
                  
 
977
                  asn = asn.substring( 0, 64 );
 
978
          }
 
979
          
 
980
          message.put( "ip_asn", asn );
 
981
      }
 
982
      
 
983
      String ui = COConfigurationManager.getStringParameter("ui");
 
984
      if (ui.length() > 0) {
 
985
        message.put("ui", ui);
 
986
      }
 
987
 
 
988
      // send locale, so we can determine which languages need attention
 
989
      message.put("locale", Locale.getDefault().toString());
 
990
      String originalLocale = System.getProperty("user.language") + "_"
 
991
                                        + System.getProperty("user.country");
 
992
      String variant = System.getProperty("user.variant");
 
993
      if (variant != null && variant.length() > 0) {
 
994
        originalLocale += "_" + variant;
 
995
      }
 
996
      message.put("orig_locale", originalLocale);
 
997
 
 
998
      if ( AzureusCoreFactory.isCoreAvailable()){
 
999
        
 
1000
              //installed plugin IDs
 
1001
              PluginInterface[] plugins = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaces();
 
1002
              List pids = new ArrayList();
 
1003
              for (int i=0;i<plugins.length;i++){
 
1004
                String  pid = plugins[i].getPluginID();
 
1005
                
 
1006
                String  info = (String)plugins[i].getPluginconfig().getPluginStringParameter( "plugin.info" );
 
1007
                
 
1008
                  // filter out built-in and core ones
 
1009
                if (    ( info != null && info.length() > 0 ) ||
 
1010
                                (       !pid.startsWith( "<" ) && 
 
1011
                                        !pid.startsWith( "azbp" ) &&
 
1012
                                        !pid.startsWith( "azupdater" ) &&
 
1013
                                        !pid.startsWith( "azplatform" ) &&
 
1014
                                        !pids.contains( pid ))){
 
1015
                
 
1016
                        if ( info != null && info.length() > 0 ){
 
1017
                                
 
1018
                                if( info.length() < 256 ){
 
1019
                                        
 
1020
                                        pid += ":" + info;
 
1021
                                        
 
1022
                                }else{
 
1023
                                        
 
1024
                                        Debug.out( "Plugin '" + pid + "' reported excessive info string '" + info + "'" );
 
1025
                                }
 
1026
                        }
 
1027
                        
 
1028
                        pids.add( pid );
 
1029
                }
 
1030
              }
 
1031
              message.put( "plugins", pids );
 
1032
      }
 
1033
    }
 
1034
    
 
1035
    
 
1036
    //swt stuff
 
1037
    try {
 
1038
      Class c = Class.forName( "org.eclipse.swt.SWT" );
 
1039
      
 
1040
      String swt_platform = (String)c.getMethod( "getPlatform", new Class[]{} ).invoke( null, new Object[]{} );
 
1041
      message.put( "swt_platform", swt_platform );
 
1042
      
 
1043
      if( send_info ) {
 
1044
        Integer swt_version = (Integer)c.getMethod( "getVersion", new Class[]{} ).invoke( null, new Object[]{} );
 
1045
        message.put( "swt_version", new Long( swt_version.longValue() ) );
 
1046
 
 
1047
        c = Class.forName("org.gudy.azureus2.ui.swt.mainwindow.MainWindow");
 
1048
                                if (c != null) {
 
1049
                                        c.getMethod("addToVersionCheckMessage", new Class[] { Map.class }).invoke(
 
1050
                                                        null, new Object[] { message });
 
1051
                                }
 
1052
      }
 
1053
    }
 
1054
    catch( ClassNotFoundException e ) {  /* ignore */ }
 
1055
    catch( NoClassDefFoundError er ) {  /* ignore */ }
 
1056
    catch( InvocationTargetException err ) {  /* ignore */ }
 
1057
    catch( Throwable t ) {  t.printStackTrace();  }
 
1058
    
 
1059
    
 
1060
    boolean using_phe = COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" );
 
1061
    message.put( "using_phe", using_phe ? new Long(1) : new Long(0) );
 
1062
    
 
1063
    return message;
 
1064
  }
 
1065
  
 
1066
  public static void
 
1067
  main(
 
1068
        String[]        args )
 
1069
  {
 
1070
          try{
 
1071
                  COConfigurationManager.initialise();
 
1072
                  
 
1073
                  boolean v6= false;
 
1074
                  
 
1075
                  System.out.println( "UDP:  " + getSingleton().getExternalIpAddressUDP(null,0,v6));
 
1076
                  System.out.println( "TCP:  " + getSingleton().getExternalIpAddressTCP(null,0,v6));
 
1077
                  System.out.println( "HTTP: " + getSingleton().getExternalIpAddressHTTP(v6));
 
1078
                  
 
1079
          }catch( Throwable e){
 
1080
                  e.printStackTrace();
 
1081
          }
 
1082
  }
 
1083
}