/** * 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, boolean v6) throws Exception { Exception error = null; Map reply = null; if (use_http) { try { reply = executeHTTP(data_to_send, v6); reply.put("protocol_used", "HTTP"); error = null; } catch (IOException e) { error = e; } catch (Exception e) { Debug.printStackTrace(e); error = e; } } if (reply == null && use_az_message) { try { reply = executeAZMessage(data_to_send, v6); reply.put("protocol_used", "AZMSG"); } catch (IOException e) { error = e; } catch (Exception e) { Debug.printStackTrace(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.")); if (v6) { last_check_time_v6 = SystemTime.getCurrentTime(); } else { last_check_time_v4 = SystemTime.getCurrentTime(); } return reply; }
private Map executeHTTP(Map data_to_send, boolean v6) throws Exception { if (v6 && !enable_v6) { throw (new Exception("IPv6 is disabled")); } String host = getHost(v6, HTTP_SERVER_ADDRESS_V6, HTTP_SERVER_ADDRESS_V4); if (Logger.isEnabled()) Logger.log( new LogEvent( LOGID, "VersionCheckClient retrieving " + "version information from " + host + ":" + HTTP_SERVER_PORT + " via HTTP")); String url_str = "http://" + (v6 ? UrlUtils.convertIPV6Host(host) : host) + (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, v6); return (reply); } finally { url_connection.disconnect(); } }
private Map executeAZMessage(Map data_to_send, boolean v6) throws Exception { if (v6 && !enable_v6) { throw (new Exception("IPv6 is disabled")); } String host = getHost(v6, AZ_MSG_SERVER_ADDRESS_V6, AZ_MSG_SERVER_ADDRESS_V4); if (Logger.isEnabled()) Logger.log( new LogEvent( LOGID, "VersionCheckClient retrieving " + "version information from " + host + ":" + AZ_MSG_SERVER_PORT)); ClientMessageService msg_service = null; Map reply = null; try { msg_service = ClientMessageServiceClient.getServerService(host, 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, v6); } finally { if (msg_service != null) { msg_service.close(); } } return (reply); }
private Map executeTCP(Map data_to_send, InetAddress bind_ip, int bind_port, boolean v6) throws Exception { if (v6 && !enable_v6) { throw (new Exception("IPv6 is disabled")); } String host = getHost(v6, TCP_SERVER_ADDRESS_V6, TCP_SERVER_ADDRESS_V4); if (Logger.isEnabled()) Logger.log( new LogEvent( LOGID, "VersionCheckClient retrieving " + "version information from " + host + ":" + TCP_SERVER_PORT + " via TCP")); String get_str = getHTTPGetString(data_to_send, false, v6); 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(host, TCP_SERVER_PORT), 10000); OutputStream os = socket.getOutputStream(); os.write(get_str.getBytes("ISO-8859-1")); os.flush(); InputStream is = socket.getInputStream(); byte[] buffer = new byte[1]; String header = ""; int content_length = -1; while (true) { int len = is.read(buffer); if (len <= 0) { break; } header += (char) buffer[0]; if (header.endsWith("\r\n\r\n")) { header = header.toLowerCase(MessageText.LOCALE_ENGLISH); int pos = header.indexOf("content-length:"); if (pos == -1) { throw (new IOException("content length missing")); } header = header.substring(pos + 15); pos = header.indexOf('\r'); header = header.substring(0, pos).trim(); content_length = Integer.parseInt(header); if (content_length > 10000) { throw (new IOException("content length too large")); } break; } if (header.length() > 2048) { throw (new IOException("header too large")); } } ByteArrayOutputStream baos = new ByteArrayOutputStream(content_length); buffer = new byte[content_length]; while (content_length > 0) { int len = is.read(buffer); if (len <= 0) { break; } baos.write(buffer, 0, len); content_length -= len; } if (content_length != 0) { throw (new IOException("error reading reply")); } byte[] reply_bytes = baos.toByteArray(); Map reply = BDecoder.decode(new BufferedInputStream(new ByteArrayInputStream(reply_bytes))); preProcessReply(reply, v6); return (reply); } finally { if (socket != null) { try { socket.close(); } catch (Throwable e) { } } } }
protected Map getVersionCheckInfoSupport( String reason, boolean only_if_cached, boolean force, boolean v6) { try { synchronized (listeners) { if (REASON_UPDATE_CHECK_START.equals(reason)) { startCheckRan = true; } for (VersionCheckClientListener l : listeners) { l.versionCheckStarted(reason); } } } catch (Throwable t) { Debug.out(t); } if (v6) { if (enable_v6) { try { check_mon.enter(); long time_diff = SystemTime.getCurrentTime() - last_check_time_v6; force = force || time_diff > CACHE_PERIOD || time_diff < 0; if (last_check_data_v6 == null || last_check_data_v6.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_v6 != null) { return (new HashMap()); } try { last_check_data_v6 = performVersionCheck(constructVersionCheckMessage(reason), true, true, true); if (last_check_data_v6 != null && last_check_data_v6.size() > 0) { COConfigurationManager.setParameter("versioncheck.cache.v6", last_check_data_v6); } } catch (SocketException t) { // internet is broken // Debug.out(t.getClass().getName() + ": " + t.getMessage()); } catch (UnknownHostException t) { // dns is broken // Debug.out(t.getClass().getName() + ": " + t.getMessage()); } catch (Throwable t) { Debug.out(t); last_check_data_v6 = new HashMap(); } } else { Logger.log( new LogEvent( LOGID, "VersionCheckClient is using " + "cached version check info. Using " + last_check_data_v6.size() + " reply keys.")); } } finally { check_mon.exit(); } } if (last_check_data_v6 == null) last_check_data_v6 = new HashMap(); return last_check_data_v6; } else { try { check_mon.enter(); long time_diff = SystemTime.getCurrentTime() - last_check_time_v4; force = force || time_diff > CACHE_PERIOD || time_diff < 0; if (last_check_data_v4 == null || last_check_data_v4.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_v4 != null) { return (new HashMap()); } try { last_check_data_v4 = performVersionCheck(constructVersionCheckMessage(reason), true, true, false); if (last_check_data_v4 != null && last_check_data_v4.size() > 0) { COConfigurationManager.setParameter("versioncheck.cache.v4", last_check_data_v4); } // clear down any plugin-specific data that has successfully been sent to the version // server try { if (AzureusCoreFactory.isCoreAvailable()) { // installed plugin IDs PluginInterface[] plugins = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaces(); for (int i = 0; i < plugins.length; i++) { PluginInterface plugin = plugins[i]; Map data = plugin .getPluginconfig() .getPluginMapParameter("plugin.versionserver.data", null); if (data != null) { plugin .getPluginconfig() .setPluginMapParameter("plugin.versionserver.data", new HashMap()); } } } } catch (Throwable e) { } } catch (UnknownHostException t) { // no internet Debug.outNoStack( "VersionCheckClient - " + t.getClass().getName() + ": " + t.getMessage()); } catch (IOException t) { // General connection problem. Debug.outNoStack( "VersionCheckClient - " + t.getClass().getName() + ": " + t.getMessage()); } catch (Throwable t) { Debug.out(t); last_check_data_v4 = new HashMap(); } } else { if (Logger.isEnabled()) Logger.log( new LogEvent( LOGID, "VersionCheckClient is using " + "cached version check info. Using " + last_check_data_v4.size() + " reply keys.")); } } finally { check_mon.exit(); } if (last_check_data_v4 == null) last_check_data_v4 = new HashMap(); last_feature_flag_cache_time = 0; return last_check_data_v4; } }
protected void preProcessReply(Map reply, final boolean v6) { NetworkAdmin admin = NetworkAdmin.getSingleton(); try { byte[] address = (byte[]) reply.get("source_ip_address"); InetAddress my_ip = InetAddress.getByName(new String(address)); NetworkAdminASN old_asn = admin.getCurrentASN(); NetworkAdminASN new_asn = admin.lookupCurrentASN(my_ip); if (!new_asn.sameAs(old_asn)) { // kick off a secondary version check to communicate the new information if (!secondary_check_done) { secondary_check_done = true; new AEThread("Secondary version check", true) { public void runSupport() { getVersionCheckInfoSupport(REASON_SECONDARY_CHECK, false, true, v6); } }.start(); } } } catch (Throwable e) { Debug.printStackTrace(e); } Long as_advice = (Long) reply.get("as_advice"); if (as_advice != null) { NetworkAdminASN current_asn = admin.getCurrentASN(); String asn = current_asn.getASName(); if (asn != null) { long advice = as_advice.longValue(); if (advice != 0) { // require crypto String done_asn = COConfigurationManager.getStringParameter("ASN Advice Followed", ""); if (!done_asn.equals(asn)) { COConfigurationManager.setParameter("ASN Advice Followed", asn); boolean change = advice == 1 || advice == 2; boolean alert = advice == 1 || advice == 3; if (!COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require")) { if (change) { COConfigurationManager.setParameter("network.transport.encrypted.require", true); } if (alert) { String msg = MessageText.getString("crypto.alert.as.warning", new String[] {asn}); Logger.log(new LogAlert(false, LogAlert.AT_WARNING, msg)); } } } } } } // set ui.toolbar.uiswitcher based on instructions from tracker // Really shouldn't be in VersionCheck client, but instead have some // listener and have the code elsewhere. Simply calling // getVersionCheckInfo from "code elsewhere" (to get the cached result) // caused a deadlock at startup. Long lEnabledUISwitcher = (Long) reply.get("ui.toolbar.uiswitcher"); if (lEnabledUISwitcher != null) { COConfigurationManager.setBooleanDefault( "ui.toolbar.uiswitcher", lEnabledUISwitcher.longValue() == 1); } }