📄 versioncheckclient.java
字号:
/*
* Created on Dec 20, 2004
* Created by Alon Rohter
* Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.azureus.core.versioncheck;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.stats.transfer.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.PluginInterface;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.clientmessageservice.*;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASNLookup;
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
import com.aelitis.net.udp.uc.PRUDPReleasablePacketHandler;
/**
* Client for checking version information from a remote server.
*/
public class VersionCheckClient {
private static final LogIDs LOGID = LogIDs.CORE;
public static final String REASON_UPDATE_CHECK_START = "us";
public static final String REASON_UPDATE_CHECK_PERIODIC = "up";
public static final String REASON_CHECK_SWT = "sw";
public static final String REASON_DHT_EXTENDED_ALLOWED = "dx";
public static final String REASON_DHT_ENABLE_ALLOWED = "de";
public static final String REASON_EXTERNAL_IP = "ip";
public static final String REASON_RECOMMENDED_PLUGINS = "rp";
public static final String REASON_SECONDARY_CHECK = "sc";
private static final String AZ_MSG_SERVER_ADDRESS = "version.aelitis.com";
private static final int AZ_MSG_SERVER_PORT = 27001;
private static final String MESSAGE_TYPE_ID = "AZVER";
public static final String HTTP_SERVER_ADDRESS = "version.aelitis.com";
public static final int HTTP_SERVER_PORT = 2080;
public static final String TCP_SERVER_ADDRESS = "version.aelitis.com";
public static final int TCP_SERVER_PORT = 2080;
public static final String UDP_SERVER_ADDRESS = "version.aelitis.com";
public static final int UDP_SERVER_PORT = 2080;
private static final long CACHE_PERIOD = 5*60*1000;
private static boolean secondary_check_done;
static{
VersionCheckClientUDPCodecs.registerCodecs();
}
private static final VersionCheckClient instance = new VersionCheckClient();
private Map last_check_data = null;
private final AEMonitor check_mon = new AEMonitor( "versioncheckclient" );
private long last_check_time = 0;
private VersionCheckClient() {
/* blank */
}
/**
* Get the singleton instance of the version check client.
* @return version check client
*/
public static VersionCheckClient getSingleton() { return instance; }
/**
* Get the version check reply info.
* @return reply data, possibly cached, if the server was already checked within the last minute
*/
public Map getVersionCheckInfo( String reason ) {
return( getVersionCheckInfoSupport( reason, false, false ));
}
protected Map
getVersionCheckInfoSupport(
String reason,
boolean only_if_cached,
boolean force )
{
try { check_mon.enter();
long time_diff = SystemTime.getCurrentTime() - last_check_time;
force = force || time_diff > CACHE_PERIOD || time_diff < 0;
if( last_check_data == null || last_check_data.size() == 0 || force ) {
// if we've never checked before then we go ahead even if the "only_if_cached"
// flag is set as its had not chance of being cached yet!
if ( only_if_cached && last_check_data != null ){
return( new HashMap() );
}
try {
last_check_data = performVersionCheck( constructVersionCheckMessage( reason ), true, true );
}
catch( Throwable t ) {
t.printStackTrace();
last_check_data = new HashMap();
}
}
else {
Logger.log(new LogEvent(LOGID, "VersionCheckClient is using "
+ "cached version check info. Using " + last_check_data.size()
+ " reply keys."));
}
}
finally { check_mon.exit(); }
if( last_check_data == null ) last_check_data = new HashMap();
return last_check_data;
}
private boolean
isVersionCheckDataValid()
{
return( last_check_data != null && last_check_data.size() > 0 );
}
/**
* Get the ip address seen by the version check server.
* NOTE: This information may be cached, see getVersionCheckInfo().
* @return external ip address, or empty string if no address information found
*/
public String
getExternalIpAddress(
boolean only_if_cached )
{
Map reply = getVersionCheckInfoSupport( REASON_EXTERNAL_IP, only_if_cached, false );
byte[] address = (byte[])reply.get( "source_ip_address" );
if( address != null ) {
return new String( address );
}
return( null );
}
/**
* Is the DHT plugin allowed to be enabled.
* @return true if DHT can be enabled, false if it should not be enabled
*/
public boolean DHTEnableAllowed() {
Map reply = getVersionCheckInfo( REASON_DHT_ENABLE_ALLOWED );
boolean res = false;
byte[] value = (byte[])reply.get( "enable_dht" );
if( value != null ) {
res = new String( value ).equalsIgnoreCase( "true" );
}
// we take the view that if the version check failed then we go ahead
// and enable the DHT (i.e. we're being optimistic)
if ( !res ){
res = !isVersionCheckDataValid();
}
return res;
}
/**
* Is the DHT allowed to be used by external plugins.
* @return true if extended DHT use is allowed, false if not allowed
*/
public boolean DHTExtendedUseAllowed() {
Map reply = getVersionCheckInfo( REASON_DHT_EXTENDED_ALLOWED );
boolean res = false;
byte[] value = (byte[])reply.get( "enable_dht_extended_use" );
if( value != null ) {
res = new String( value ).equalsIgnoreCase( "true" );
}
// be generous and enable extended use if check failed
if ( !res ){
res = !isVersionCheckDataValid();
}
return res;
}
public String[]
getRecommendedPlugins()
{
Map reply = getVersionCheckInfo( REASON_RECOMMENDED_PLUGINS );
List l = (List)reply.get( "recommended_plugins" );
if ( l == null ){
return( new String[0] );
}
String[] res = new String[l.size()];
for (int i=0;i<l.size();i++){
res[i] = new String((byte[])l.get(i));
}
return( res );
}
/**
* Perform the actual version check by connecting to the version server.
* @param data_to_send version message
* @return version reply
* @throws Exception if the server check connection fails
*/
private Map
performVersionCheck(
Map data_to_send,
boolean use_az_message,
boolean use_http )
throws Exception
{
Exception error = null;
Map reply = null;
if ( use_az_message ){
try{
reply = executeAZMessage( data_to_send );
reply.put( "protocol_used", "AZMSG" );
}catch( Exception e ){
error = e;
}
}
if ( reply == null && use_http ){
try{
reply = executeHTTP( data_to_send );
reply.put( "protocol_used", "HTTP" );
error = null;
}catch( Exception e ){
error = e;
}
}
if ( error != null ){
throw( error );
}
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "VersionCheckClient server "
+ "version check successful. Received " + reply.size()
+ " reply keys."));
last_check_time = SystemTime.getCurrentTime();
return reply;
}
private Map
executeAZMessage(
Map data_to_send )
throws Exception
{
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
+ "version information from " + AZ_MSG_SERVER_ADDRESS + ":" + AZ_MSG_SERVER_PORT));
ClientMessageService msg_service = null;
Map reply = null;
try{
msg_service = ClientMessageServiceClient.getServerService( AZ_MSG_SERVER_ADDRESS, AZ_MSG_SERVER_PORT, MESSAGE_TYPE_ID );
msg_service.sendMessage( data_to_send ); //send our version message
reply = msg_service.receiveMessage(); //get the server reply
preProcessReply( reply );
}finally{
if ( msg_service != null ){
msg_service.close();
}
}
return( reply );
}
private Map
executeHTTP(
Map data_to_send )
throws Exception
{
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
+ "version information from " + HTTP_SERVER_ADDRESS + ":" + HTTP_SERVER_PORT + " via HTTP" ));
String url_str = "http://" + HTTP_SERVER_ADDRESS + (HTTP_SERVER_PORT==80?"":(":" + HTTP_SERVER_PORT)) + "/version?";
url_str += URLEncoder.encode( new String( BEncoder.encode( data_to_send ), "ISO-8859-1" ), "ISO-8859-1" );
URL url = new URL( url_str );
HttpURLConnection url_connection = (HttpURLConnection)url.openConnection();
url_connection.connect();
try{
InputStream is = url_connection.getInputStream();
Map reply = BDecoder.decode( new BufferedInputStream( is ));
preProcessReply( reply );
return( reply );
}finally{
url_connection.disconnect();
}
}
public String
getHTTPGetString(
boolean for_proxy )
{
return( getHTTPGetString( new HashMap(), for_proxy));
}
private String
getHTTPGetString(
Map content,
boolean for_proxy )
{
String get_str = "GET " + (for_proxy?("http://" + HTTP_SERVER_ADDRESS + ":" + HTTP_SERVER_PORT ):"") +"/version?";
try{
get_str += URLEncoder.encode( new String( BEncoder.encode( content ), "ISO-8859-1" ), "ISO-8859-1" );
}catch( Throwable e ){
}
get_str +=" HTTP/1.1" + "\015\012" + "\015\012";
return( get_str );
}
private Map
executeTCP(
Map data_to_send,
InetAddress bind_ip,
int bind_port )
throws Exception
{
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "VersionCheckClient retrieving "
+ "version information from " + TCP_SERVER_ADDRESS + ":" + TCP_SERVER_PORT + " via TCP" ));
String get_str = getHTTPGetString( data_to_send, false );
Socket socket = null;
try{
socket = new Socket();
if ( bind_ip != null ){
socket.bind( new InetSocketAddress( bind_ip, bind_port ));
}else if ( bind_port != 0 ){
socket.bind( new InetSocketAddress( bind_port ));
}
socket.setSoTimeout( 10000 );
socket.connect( new InetSocketAddress( TCP_SERVER_ADDRESS, TCP_SERVER_PORT ), 10000 );
OutputStream os = socket.getOutputStream();
os.write( get_str.getBytes( "ISO-8859-1" ));
os.flush();
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -