use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class TorrentDownloaderImpl method runSupport.
@Override
public void runSupport() {
try {
// determine if this is already a proper URL
new URL(url_str);
} catch (Throwable t) {
// it's not
// check if the string is just a base32/hex-encoded torrent infohash
String magnet_uri = UrlUtils.normaliseMagnetURI(url_str);
if (magnet_uri != null) {
url_str = magnet_uri;
}
}
try {
url = AddressUtils.adjustURL(new URL(url_str));
String protocol = url.getProtocol().toLowerCase(Locale.US);
if (protocol.equals("magnet") || protocol.equals("maggot") || protocol.equals("dht")) {
url = AddressUtils.adjustURL(new URL(url_str + (url_str.contains("?") ? "&" : "?") + "pause_on_error=true"));
}
Set<String> redirect_urls = new HashSet<>();
boolean follow_redirect = true;
URL current_url = url;
Proxy current_proxy = proxy;
PluginProxy current_plugin_proxy = AEProxyFactory.getPluginProxy(current_proxy);
redirect_label: while (follow_redirect) {
follow_redirect = false;
boolean dh_hack = false;
boolean internal_error_hack = false;
for (int connect_loop = 0; connect_loop < 3; connect_loop++) {
protocol = current_url.getProtocol().toLowerCase(Locale.US);
try {
if (protocol.equals("https")) {
// see ConfigurationChecker for SSL client defaults
HttpsURLConnection ssl_con;
if (current_proxy == null) {
ssl_con = (HttpsURLConnection) current_url.openConnection();
} else {
ssl_con = (HttpsURLConnection) current_url.openConnection(current_proxy);
}
if (!internal_error_hack) {
// allow for certs that contain IP addresses rather than dns names
ssl_con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession session) {
return (true);
}
});
}
if (dh_hack) {
UrlUtils.DHHackIt(ssl_con);
}
if (connect_loop > 0) {
// meh, some https trackers are just screwed
TrustManager[] trustAllCerts = SESecurityManager.getAllTrustingTrustManager();
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, RandomUtils.SECURE_RANDOM);
SSLSocketFactory factory = sc.getSocketFactory();
ssl_con.setSSLSocketFactory(factory);
} catch (Throwable e) {
}
}
if (internal_error_hack) {
if (current_plugin_proxy != null) {
String host = current_plugin_proxy.getURLHostRewrite();
UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
}
}
con = ssl_con;
} else {
if (current_proxy == null) {
con = current_url.openConnection();
} else {
con = current_url.openConnection(current_proxy);
}
}
if (con instanceof HttpURLConnection) {
// we want this true but some plugins (grrr) set the global default not to follow
// redirects
((HttpURLConnection) con).setInstanceFollowRedirects(proxy == null);
}
Properties props = new Properties();
ClientIDManagerImpl.getSingleton().getGenerator().generateHTTPProperties(null, props);
String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
con.setRequestProperty("User-Agent", ua);
if (referrer != null && referrer.length() > 0) {
con.setRequestProperty("Referer", referrer);
}
if (request_properties != null) {
Iterator it = request_properties.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (!key.equalsIgnoreCase("Accept-Encoding")) {
con.setRequestProperty(key, value);
}
}
}
this.con.connect();
String magnetURI = con.getHeaderField("Magnet-Uri");
if (magnetURI != null) {
closeConnection();
url_str = magnetURI;
runSupport();
return;
}
int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
// auto redirect doesn't work from http to https or vice-versa
String move_to = con.getHeaderField("location");
if (move_to != null) {
if (redirect_urls.contains(move_to) || redirect_urls.size() > 32) {
break;
}
redirect_urls.add(move_to);
try {
// don't URL decode the move-to as its already in the right format!
// URLDecoder.decode( move_to, "UTF-8" ));
URL move_to_url = new URL(move_to);
boolean follow = false;
if (current_plugin_proxy != null) {
PluginProxy child = current_plugin_proxy.getChildProxy("redirect", move_to_url);
if (child != null) {
// use an overall property to force this through on the redirect
request_properties.put("HOST", child.getURLHostRewrite() + (move_to_url.getPort() == -1 ? "" : (":" + move_to_url.getPort())));
current_proxy = child.getProxy();
move_to_url = child.getURL();
follow = true;
}
}
String original_protocol = current_url.getProtocol().toLowerCase();
String new_protocol = move_to_url.getProtocol().toLowerCase();
if (follow || !original_protocol.equals(new_protocol)) {
current_url = move_to_url;
try {
List<String> cookies_list = con.getHeaderFields().get("Set-cookie");
List<String> cookies_set = new ArrayList<>();
if (cookies_list != null) {
for (int i = 0; i < cookies_list.size(); i++) {
String[] cookie_bits = ((String) cookies_list.get(i)).split(";");
if (cookie_bits.length > 0) {
cookies_set.add(cookie_bits[0]);
}
}
}
if (cookies_set.size() > 0) {
String new_cookies = "";
Object obj = request_properties.get("Cookie");
if (obj instanceof String) {
new_cookies = (String) obj;
}
for (String s : cookies_set) {
new_cookies += (new_cookies.length() == 0 ? "" : "; ") + s;
}
request_properties.put("Cookie", new_cookies);
}
} catch (Throwable e) {
Debug.out(e);
}
follow_redirect = true;
continue redirect_label;
}
} catch (Throwable e) {
}
}
}
break;
} catch (SSLException e) {
if (connect_loop < 3) {
String msg = Debug.getNestedExceptionMessage(e);
boolean try_again = false;
if (msg.contains("DH keypair")) {
if (!dh_hack) {
dh_hack = true;
try_again = true;
}
} else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
if (!internal_error_hack) {
internal_error_hack = true;
try_again = true;
}
}
if (current_plugin_proxy == null) {
if (SESecurityManager.installServerCertificates(url) != null) {
// certificate has been installed
try_again = true;
}
}
if (url != current_url && current_plugin_proxy == null && SESecurityManager.installServerCertificates(current_url) != null) {
// certificate has been installed
try_again = true;
}
if (try_again) {
continue;
}
}
throw (e);
} catch (IOException e) {
if (connect_loop == 0) {
URL retry_url = UrlUtils.getIPV4Fallback(url);
if (retry_url != null) {
url = retry_url;
} else {
throw (e);
}
}
if (e instanceof UnknownHostException) {
throw (e);
}
}
}
}
int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
if (!ignoreReponseCode) {
if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
this.error(response, Integer.toString(response) + ": " + ((HttpURLConnection) con).getResponseMessage());
return;
}
}
/*
Map headerFields = this.con.getHeaderFields();
System.out.println("Header of download of " + url_str);
for (Iterator iter = headerFields.keySet().iterator(); iter.hasNext();) {
String s = (String) iter.next();
System.out.println(s + ":" + headerFields.get(s));
}
*/
filename = this.con.getHeaderField("Content-Disposition");
if ((filename != null) && filename.toLowerCase().matches(".*attachment.*")) {
while (filename.toLowerCase().charAt(0) != 'a') {
filename = filename.substring(1);
}
}
// see if we can grab the filename directly (thanks Angel)
Pattern p = Pattern.compile(".*filename=\\\"(.*)\\\"");
Matcher m = null;
if (filename != null && ((m = p.matcher(filename)) != null) && m.matches()) {
filename = m.group(1).trim();
} else if (filename == null || !filename.toLowerCase().startsWith("attachment") || filename.indexOf('=') == -1) {
String tmp = this.url.getFile();
if (tmp.length() == 0 || tmp.equals("/")) {
filename = url.getHost();
} else if (tmp.startsWith("?")) {
// probably a magnet URI - use the hash
// magnet:?xt=urn:sha1:VGC53ZWCUXUWVGX7LQPVZIYF4L6RXSU6
String query = tmp.toUpperCase();
int pos = query.indexOf("XT=URN:SHA1:");
if (pos == -1) {
pos = query.indexOf("XT=URN:BTIH:");
}
if (pos != -1) {
pos += 12;
int p2 = query.indexOf("&", pos);
if (p2 == -1) {
filename = query.substring(pos);
} else {
filename = query.substring(pos, p2);
}
} else {
filename = "Torrent" + (long) (Math.random() * Long.MAX_VALUE);
}
filename += ".tmp";
} else {
while (tmp.endsWith("/")) {
tmp = tmp.substring(0, tmp.length() - 1);
}
if (tmp.lastIndexOf('/') != -1) {
tmp = tmp.substring(tmp.lastIndexOf('/') + 1);
}
// remove any params in the url
int param_pos = tmp.indexOf('?');
if (param_pos != -1) {
tmp = tmp.substring(0, param_pos);
}
filename = URLDecoder.decode(tmp, Constants.DEFAULT_ENCODING);
if (filename.length() == 0) {
filename = "Torrent" + (long) (Math.random() * Long.MAX_VALUE);
}
}
} else {
filename = filename.substring(filename.indexOf('=') + 1);
if (filename.startsWith("\"") && filename.endsWith("\""))
filename = filename.substring(1, filename.lastIndexOf('\"'));
filename = URLDecoder.decode(filename, Constants.DEFAULT_ENCODING);
// this code removes any parent directories from the filename we've extracted
File temp = new File(filename);
filename = temp.getName();
}
filename = FileUtil.convertOSSpecificChars(filename, false);
directoryname = COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory");
boolean useTorrentSave = COConfigurationManager.getBooleanParameter("Save Torrent Files");
if (file_str != null) {
// not completely sure about the whole logic in this block
File temp = new File(file_str);
// if we're not using a default torrent save dir
if (!useTorrentSave || directoryname.length() == 0) {
// if it's already a dir
if (temp.isDirectory()) {
// use it
directoryname = temp.getCanonicalPath();
} else // it's a file
{
// so use its parent dir
directoryname = temp.getCanonicalFile().getParent();
}
}
// if it's a file
if (!temp.isDirectory()) {
// set the file name
filename = temp.getName();
}
}
// what would happen here if directoryname == null and file_str == null??
this.state = STATE_INIT;
this.notifyListener();
} catch (java.net.MalformedURLException e) {
this.error(0, "Exception while parsing URL '" + url_str + "':" + e.getMessage());
} catch (java.net.UnknownHostException e) {
this.error(0, "Exception while initializing download of '" + url + "': Unknown Host '" + e.getMessage() + "'");
} catch (java.io.IOException ioe) {
this.error(0, "I/O Exception while initializing download of '" + url + "':" + ioe.toString());
} catch (Throwable e) {
this.error(0, "Exception while initializing download of '" + url + "':" + e.toString());
}
if (this.state == STATE_ERROR) {
return;
}
try {
final boolean[] status_reader_run = { true };
this.state = STATE_START;
notifyListener();
this.state = STATE_DOWNLOADING;
notifyListener();
if (con instanceof HttpURLConnection) {
Thread status_reader = new AEThread("TorrentDownloader:statusreader") {
@Override
public void runSupport() {
HttpURLConnection http_con = (HttpURLConnection) con;
boolean changed_status = false;
String last_status = "";
boolean sleep = false;
long last_progress_update = SystemTime.getMonotonousTime();
while (true) {
try {
if (sleep) {
Thread.sleep(50);
sleep = false;
}
try {
this_mon.enter();
if (!status_reader_run[0]) {
break;
}
} finally {
this_mon.exit();
}
String s = http_con.getResponseMessage();
if (s.equals(last_status)) {
sleep = true;
} else {
last_status = s;
String lc_s = s.toLowerCase();
if (!lc_s.startsWith("error:")) {
if (s.toLowerCase().contains("alive")) {
if (percentDone < 10) {
percentDone++;
}
}
boolean progress_update = false;
int pos = s.indexOf('%');
if (pos != -1) {
int i;
for (i = pos - 1; i >= 0; i--) {
char c = s.charAt(i);
if (!Character.isDigit(c) && c != ' ') {
i++;
break;
}
}
try {
percentDone = Integer.parseInt(s.substring(i, pos).trim());
progress_update = true;
} catch (Throwable e) {
}
}
if (lc_s.startsWith("received")) {
progress_update = true;
}
if (progress_update) {
long now = SystemTime.getMonotonousTime();
if (now - last_progress_update < 250) {
continue;
}
last_progress_update = now;
}
setStatus(s);
} else {
error(http_con.getResponseCode(), s.substring(6));
}
changed_status = true;
}
} catch (Throwable e) {
break;
}
}
if (changed_status) {
setStatus("");
}
}
};
status_reader.setDaemon(true);
status_reader.start();
}
InputStream in = null;
FileOutputStream fileout = null;
try {
try {
in = this.con.getInputStream();
} catch (FileNotFoundException e) {
if (ignoreReponseCode) {
if (con instanceof HttpURLConnection) {
in = ((HttpURLConnection) con).getErrorStream();
} else {
in = null;
}
} else {
throw e;
}
} finally {
try {
this_mon.enter();
status_reader_run[0] = false;
} finally {
this_mon.exit();
}
}
// handle some servers that return gzip'd torrents even though we don't request it!
String encoding = con.getHeaderField("content-encoding");
if (encoding != null) {
if (encoding.equalsIgnoreCase("gzip")) {
in = new GZIPInputStream(in);
} else if (encoding.equalsIgnoreCase("deflate")) {
in = new InflaterInputStream(in);
}
}
if (this.state != STATE_ERROR) {
this.file = new File(this.directoryname, filename);
boolean useTempFile = file.exists();
if (!useTempFile) {
try {
this.file.createNewFile();
useTempFile = !this.file.exists();
} catch (Throwable t) {
useTempFile = true;
}
}
if (useTempFile) {
this.file = File.createTempFile("AZU", ".torrent", new File(this.directoryname));
this.file.createNewFile();
}
fileout = new FileOutputStream(this.file, false);
bufBytes = 0;
int size = (int) UrlUtils.getContentLength(con);
this.percentDone = -1;
do {
if (this.cancel) {
break;
}
try {
bufBytes = in.read(buf);
this.readTotal += bufBytes;
if (size > 0) {
this.percentDone = (100 * this.readTotal) / size;
}
notifyListener();
} catch (IOException e) {
}
if (bufBytes > 0) {
fileout.write(buf, 0, bufBytes);
}
} while (bufBytes > 0);
in.close();
fileout.flush();
fileout.close();
if (this.cancel) {
this.state = STATE_CANCELLED;
if (deleteFileOnCancel) {
this.cleanUpFile();
}
} else {
if (this.readTotal <= 0) {
this.error(0, "No data contained in '" + this.url.toString() + "'");
return;
}
try {
if (!filename.toLowerCase().endsWith(".torrent")) {
TOTorrent torrent = TorrentUtils.readFromFile(file, false);
String name = TorrentUtils.getLocalisedName(torrent) + ".torrent";
File new_file = new File(directoryname, name);
if (file.renameTo(new_file)) {
filename = name;
file = new_file;
}
}
} catch (Throwable e) {
boolean is_vuze_file = false;
try {
if (VuzeFileHandler.isAcceptedVuzeFileName(filename)) {
is_vuze_file = true;
} else {
if (VuzeFileHandler.getSingleton().loadVuzeFile(file) != null) {
is_vuze_file = true;
String name = VuzeFileHandler.getVuzeFileName(filename);
File new_file = new File(directoryname, name);
if (file.renameTo(new_file)) {
filename = name;
file = new_file;
}
}
}
} catch (Throwable f) {
}
if (!is_vuze_file) {
if (!RSSUtils.isRSSFeed(file)) {
Debug.printStackTrace(e);
}
}
}
if (proxy == null) {
TorrentUtils.setObtainedFrom(file, original_url);
}
this.state = STATE_FINISHED;
}
this.notifyListener();
}
} finally {
if (in != null) {
try {
in.close();
} catch (Throwable e) {
}
}
if (fileout != null) {
try {
fileout.close();
} catch (Throwable e) {
}
}
}
} catch (Throwable e) {
String url_log_string = this.url_str.toString().replaceAll("\\Q&pause_on_error=true\\E", "");
String log_msg = MessageText.getString("torrentdownload.error.dl_fail", new String[] { url_log_string, file == null ? filename : file.getAbsolutePath(), e.getMessage() });
if (!cancel) {
Debug.out(log_msg, e);
}
this.error(0, log_msg);
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class ResourceDownloaderURLImpl method download.
@Override
public InputStream download() throws ResourceDownloaderException {
try {
reportActivity(this, getLogIndent() + "Downloading: " + trimForDisplay(original_url));
try {
this_mon.enter();
if (download_initiated) {
throw (new ResourceDownloaderException(this, "Download already initiated"));
}
download_initiated = true;
} finally {
this_mon.exit();
}
try {
URL outer_url = new URL(original_url.toString().replaceAll(" ", "%20"));
// some authentications screw up without an explicit port number here
String protocol = outer_url.getProtocol().toLowerCase();
if (protocol.equals("vuze") || protocol.equals("biglybt")) {
outer_url = original_url;
} else if (protocol.equals("file")) {
File file = new File(original_url.toURI());
FileInputStream fis = new FileInputStream(file);
informAmountComplete(file.length());
informPercentDone(100);
informComplete(fis);
return (fis);
} else if (outer_url.getPort() == -1 && (protocol.equals("http") || protocol.equals("https"))) {
int target_port;
if (protocol.equals("http")) {
target_port = 80;
} else {
target_port = 443;
}
try {
String str = original_url.toString().replaceAll(" ", "%20");
int pos = str.indexOf("://");
pos = str.indexOf("/", pos + 4);
if (pos == -1) {
outer_url = new URL(str + ":" + target_port + "/");
} else {
outer_url = new URL(str.substring(0, pos) + ":" + target_port + str.substring(pos));
}
} catch (Throwable e) {
Debug.printStackTrace(e);
}
}
outer_url = AddressUtils.adjustURL(outer_url);
try {
if (force_no_proxy) {
AEProxySelectorFactory.getSelector().startNoProxy();
}
if (auth_supplied) {
SESecurityManager.setPasswordHandler(outer_url, this);
}
boolean use_compression = true;
boolean follow_redirect = true;
boolean dh_hack = false;
boolean internal_error_hack = false;
Set<String> redirect_urls = new HashSet<>();
URL current_url = outer_url;
Proxy current_proxy = force_proxy;
PluginProxy current_plugin_proxy = null;
URL initial_url = current_url;
redirect_label: while (follow_redirect) {
follow_redirect = false;
PluginProxy plugin_proxy_auto;
boolean ok = false;
if (auto_plugin_proxy || isAnonymous()) {
plugin_proxy_auto = AEProxyFactory.getPluginProxy("downloading resource", current_url);
if (plugin_proxy_auto == null) {
throw (new ResourceDownloaderException(this, "No plugin proxy available"));
}
current_url = plugin_proxy_auto.getURL();
current_proxy = plugin_proxy_auto.getProxy();
} else {
plugin_proxy_auto = null;
}
try {
SSLSocketFactory ssl_socket_factory = null;
for (int connect_loop = 0; connect_loop < 3; connect_loop++) {
File temp_file = null;
try {
URLConnection con;
current_plugin_proxy = plugin_proxy_auto == null ? AEProxyFactory.getPluginProxy(force_proxy) : plugin_proxy_auto;
if (current_url.getProtocol().equalsIgnoreCase("https")) {
// see ConfigurationChecker for SSL client defaults
HttpsURLConnection ssl_con = (HttpsURLConnection) openConnection(current_proxy, current_url);
if (ssl_socket_factory != null) {
ssl_con.setSSLSocketFactory(ssl_socket_factory);
}
if (!internal_error_hack) {
// for some reason, on java 8 at least, even setting a host name verifier
// causes an SSL internal_error on some websites :(
// allow for certs that contain IP addresses rather than dns names
ssl_con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession session) {
return (true);
}
});
}
if (current_plugin_proxy != null) {
// unfortunately the use of an intermediate host name causes
// SSL to completely fail (the hostname verifier above isn't enough to
// stop borkage) so what can we do?
// actually, not sure why, but when I hacked in this delegator things magically
// started working :(
TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
final List<X509TrustManager> default_tms = new ArrayList<>();
if (tmf != null) {
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
default_tms.add((X509TrustManager) tm);
}
}
}
TrustManager[] tms_delegate = SESecurityManager.getAllTrustingTrustManager(new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
List<X509Certificate> result = new ArrayList<>();
for (X509TrustManager tm : default_tms) {
result.addAll(Arrays.asList(tm.getAcceptedIssuers()));
}
return (result.toArray(new X509Certificate[result.size()]));
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager tm : default_tms) {
tm.checkClientTrusted(chain, authType);
}
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager tm : default_tms) {
tm.checkServerTrusted(chain, authType);
}
}
});
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, tms_delegate, RandomUtils.SECURE_RANDOM);
SSLSocketFactory factory = sc.getSocketFactory();
ssl_con.setSSLSocketFactory(factory);
}
if (dh_hack) {
UrlUtils.DHHackIt(ssl_con);
}
if (internal_error_hack && current_plugin_proxy != null) {
String host = current_plugin_proxy.getURLHostRewrite();
UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
}
con = ssl_con;
} else {
con = openConnection(current_proxy, current_url);
}
if (con instanceof HttpURLConnection) {
if (current_plugin_proxy != null) {
// need to manually handle redirects as we need to re-proxy
((HttpURLConnection) con).setInstanceFollowRedirects(false);
} else {
((HttpURLConnection) con).setInstanceFollowRedirects(true);
}
}
if (current_plugin_proxy != null) {
con.setRequestProperty("HOST", current_plugin_proxy.getURLHostRewrite() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
}
ClientIDGenerator cidg = ClientIDManagerImpl.getSingleton().getGenerator();
if (cidg != null) {
Properties props = new Properties();
cidg.generateHTTPProperties(null, props);
String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
con.setRequestProperty("User-Agent", ua);
}
String connection = getStringProperty("URL_Connection");
if (connection != null && connection.equalsIgnoreCase("Keep-Alive")) {
con.setRequestProperty("Connection", "Keep-Alive");
// gah, no idea what the intent behind 'skip' is!
} else if (connection == null || !connection.equals("skip")) {
// default is close
con.setRequestProperty("Connection", "close");
}
if (use_compression) {
con.addRequestProperty("Accept-Encoding", "gzip");
}
setRequestProperties(con, use_compression);
if (post_data != null && con instanceof HttpURLConnection) {
con.setDoOutput(true);
String verb = (String) getStringProperty("URL_HTTP_VERB");
if (verb == null) {
verb = "POST";
}
((HttpURLConnection) con).setRequestMethod(verb);
if (post_data.length > 0) {
OutputStream os = con.getOutputStream();
os.write(post_data);
os.flush();
}
}
long connect_timeout = getLongProperty("URL_Connect_Timeout");
if (connect_timeout >= 0) {
con.setConnectTimeout((int) connect_timeout);
}
long read_timeout = getLongProperty("URL_Read_Timeout");
if (read_timeout >= 0) {
con.setReadTimeout((int) read_timeout);
}
boolean trust_content_length = getBooleanProperty("URL_Trust_Content_Length");
try {
con.connect();
} catch (AEProxyFactory.UnknownHostException e) {
throw (new UnknownHostException(e.getMessage()));
}
int response = con instanceof HttpURLConnection ? ((HttpURLConnection) con).getResponseCode() : HttpURLConnection.HTTP_OK;
ok = true;
if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
// auto redirect doesn't work from http to https or vice-versa
String move_to = con.getHeaderField("location");
if (move_to != null) {
if (redirect_urls.contains(move_to) || redirect_urls.size() > 32) {
throw (new ResourceDownloaderException(this, "redirect loop"));
}
redirect_urls.add(move_to);
try {
// don't URL decode the move-to as its already in the right format!
// URLDecoder.decode( move_to, "UTF-8" ));
URL move_to_url = new URL(move_to);
boolean follow = false;
if (current_plugin_proxy != null) {
PluginProxy child = current_plugin_proxy.getChildProxy("redirect", move_to_url);
if (child != null) {
initial_url = move_to_url;
// use an overall property to force this through on the redirect
setProperty("URL_HOST", initial_url.getHost() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
current_proxy = child.getProxy();
move_to_url = child.getURL();
follow = true;
}
}
String original_protocol = current_url.getProtocol().toLowerCase();
String new_protocol = move_to_url.getProtocol().toLowerCase();
if (follow || !original_protocol.equals(new_protocol)) {
current_url = move_to_url;
try {
List<String> cookies_list = con.getHeaderFields().get("Set-cookie");
List<String> cookies_set = new ArrayList<>();
if (cookies_list != null) {
for (int i = 0; i < cookies_list.size(); i++) {
String[] cookie_bits = ((String) cookies_list.get(i)).split(";");
if (cookie_bits.length > 0) {
cookies_set.add(cookie_bits[0]);
}
}
}
if (cookies_set.size() > 0) {
String new_cookies = "";
Map properties = getLCKeyProperties();
Object obj = properties.get("url_cookie");
if (obj instanceof String) {
new_cookies = (String) obj;
}
for (String s : cookies_set) {
new_cookies += (new_cookies.length() == 0 ? "" : "; ") + s;
}
setProperty("URL_Cookie", new_cookies);
}
} catch (Throwable e) {
Debug.out(e);
}
follow_redirect = true;
continue redirect_label;
}
} catch (Throwable e) {
}
}
}
setProperty("URL_HTTP_Response", new Long(response));
if (response != HttpURLConnection.HTTP_CREATED && response != HttpURLConnection.HTTP_ACCEPTED && response != HttpURLConnection.HTTP_NO_CONTENT && response != HttpURLConnection.HTTP_OK) {
HttpURLConnection http_con = (HttpURLConnection) con;
InputStream error_stream = http_con.getErrorStream();
String error_str = null;
if (error_stream != null) {
String encoding = con.getHeaderField("content-encoding");
if (encoding != null) {
if (encoding.equalsIgnoreCase("gzip")) {
error_stream = new GZIPInputStream(error_stream);
} else if (encoding.equalsIgnoreCase("deflate")) {
error_stream = new InflaterInputStream(error_stream);
}
}
error_str = FileUtil.readInputStreamAsString(error_stream, 512);
}
// grab properties anyway as they may be useful
getRequestProperties(con);
URL dest = current_url;
if (current_plugin_proxy != null) {
try {
dest = new URL(current_plugin_proxy.getTarget());
} catch (Throwable e) {
}
}
throw (new ResourceDownloaderException(this, "Error on connect for '" + trimForDisplay(dest) + "': " + Integer.toString(response) + " " + http_con.getResponseMessage() + (error_str == null ? "" : (": error=" + error_str))));
}
getRequestProperties(con);
boolean compressed = false;
try {
this_mon.enter();
input_stream = con.getInputStream();
String encoding = con.getHeaderField("content-encoding");
if (encoding != null) {
if (encoding.equalsIgnoreCase("gzip")) {
compressed = true;
input_stream = new GZIPInputStream(input_stream);
} else if (encoding.equalsIgnoreCase("deflate")) {
compressed = true;
input_stream = new InflaterInputStream(input_stream);
}
}
} finally {
this_mon.exit();
}
if (con instanceof MagnetConnection2) {
// hack - status reports for magnet connections are returned
List<String> errors = ((MagnetConnection2) con).getResponseMessages(true);
if (errors.size() > 0) {
throw (new ResourceDownloaderException(this, errors.get(0)));
}
}
ByteArrayOutputStream baos = null;
FileOutputStream fos = null;
try {
byte[] buf = new byte[BUFFER_SIZE];
long total_read = 0;
// unfortunately not all servers set content length
/* From Apache's mod_deflate doc:
* http://httpd.apache.org/docs/2.0/mod/mod_deflate.html
Note on Content-Length
If you evaluate the request body yourself, don't trust the
Content-Length header! The Content-Length header reflects
the length of the incoming data from the client and not the
byte count of the decompressed data stream.
*/
long size = compressed ? -1 : UrlUtils.getContentLength(con);
baos = size > 0 ? new ByteArrayOutputStream(size > MAX_IN_MEM_READ_SIZE ? MAX_IN_MEM_READ_SIZE : (int) size) : new ByteArrayOutputStream();
while (!cancel_download) {
if (size >= 0 && total_read >= size && trust_content_length) {
break;
}
int read = input_stream.read(buf);
if (read > 0) {
if (total_read > MAX_IN_MEM_READ_SIZE) {
if (fos == null) {
temp_file = AETemporaryFileHandler.createTempFile();
fos = new FileOutputStream(temp_file);
fos.write(baos.toByteArray());
baos = null;
}
fos.write(buf, 0, read);
} else {
baos.write(buf, 0, read);
}
total_read += read;
informAmountComplete(total_read);
if (size > 0) {
informPercentDone((int) ((100 * total_read) / size));
}
} else {
break;
}
}
if (size > 0 && total_read != size) {
if (total_read > size) {
// this has been seen with UPnP linksys - more data is read than
// the content-length has us believe is coming (1 byte in fact...)
Debug.outNoStack("Inconsistent stream length for '" + trimForDisplay(original_url) + "': expected = " + size + ", actual = " + total_read);
} else {
throw (new IOException("Premature end of stream"));
}
}
} finally {
if (fos != null) {
try {
fos.close();
} catch (Throwable e) {
}
}
input_stream.close();
}
InputStream res;
if (temp_file != null) {
res = new DeleteFileOnCloseInputStream(temp_file);
temp_file = null;
} else {
res = new ByteArrayInputStream(baos.toByteArray());
}
boolean handed_over = false;
try {
if (informComplete(res)) {
handed_over = true;
return (res);
}
} finally {
if (!handed_over) {
res.close();
}
}
throw (new ResourceDownloaderException(this, "Contents downloaded but rejected: '" + trimForDisplay(original_url) + "'"));
} catch (SSLException e) {
String msg = Debug.getNestedExceptionMessage(e);
if (connect_loop < 3) {
boolean try_again = false;
if (msg.contains("DH keypair")) {
if (!dh_hack) {
dh_hack = true;
try_again = true;
}
} else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
if (!internal_error_hack) {
internal_error_hack = true;
try_again = true;
}
}
ssl_socket_factory = SESecurityManager.installServerCertificates(current_url);
if (ssl_socket_factory != null) {
// certificate has been installed
try_again = true;
}
if (try_again) {
continue;
}
}
throw (e);
} catch (ZipException e) {
if (connect_loop == 0) {
use_compression = false;
continue;
}
} catch (IOException e) {
if (connect_loop == 0) {
String msg = e.getMessage();
if (msg != null) {
msg = msg.toLowerCase(MessageText.LOCALE_ENGLISH);
if (msg.contains("gzip")) {
use_compression = false;
continue;
}
}
URL retry_url = UrlUtils.getIPV4Fallback(current_url);
if (retry_url != null) {
current_url = retry_url;
continue;
}
}
throw (e);
} finally {
if (temp_file != null) {
temp_file.delete();
}
}
}
} finally {
if (plugin_proxy_auto != null) {
plugin_proxy_auto.setOK(ok);
}
}
}
throw (new ResourceDownloaderException(this, "Should never get here"));
} finally {
if (auth_supplied) {
SESecurityManager.setPasswordHandler(outer_url, null);
}
if (force_no_proxy) {
AEProxySelectorFactory.getSelector().endNoProxy();
}
}
} catch (java.net.MalformedURLException e) {
throw (new ResourceDownloaderException(this, "Exception while parsing URL '" + trimForDisplay(original_url) + "':" + e.getMessage(), e));
} catch (java.net.UnknownHostException e) {
throw (new ResourceDownloaderException(this, "Exception while initializing download of '" + trimForDisplay(original_url) + "': Unknown Host '" + e.getMessage() + "'", e));
} catch (java.io.IOException e) {
throw (new ResourceDownloaderException(this, "I/O Exception while downloading '" + trimForDisplay(original_url) + "'", e));
}
} catch (Throwable e) {
ResourceDownloaderException rde;
if (e instanceof ResourceDownloaderException) {
rde = (ResourceDownloaderException) e;
} else {
Debug.out(e);
rde = new ResourceDownloaderException(this, "Unexpected error", e);
}
informFailed(rde);
throw (rde);
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class ResourceDownloaderURLImpl method getSizeSupport.
protected long getSizeSupport() throws ResourceDownloaderException {
try {
String protocol = original_url.getProtocol().toLowerCase();
if (protocol.equals("magnet") || protocol.equals("maggot") || protocol.equals("dht") || protocol.equals("vuze") || protocol.equals("biglybt") || protocol.equals("azplug") || protocol.equals("ftp")) {
return (-1);
} else if (protocol.equals("file")) {
return (new File(original_url.toURI()).length());
}
reportActivity(this, "Getting size of " + original_url);
try {
URL url = new URL(original_url.toString().replaceAll(" ", "%20"));
url = AddressUtils.adjustURL(url);
URL initial_url = url;
PluginProxy plugin_proxy;
boolean ok = false;
if (auto_plugin_proxy || isAnonymous()) {
plugin_proxy = AEProxyFactory.getPluginProxy("downloading resource", url);
if (plugin_proxy == null) {
throw (new ResourceDownloaderException(this, "No plugin proxy available"));
}
url = plugin_proxy.getURL();
force_proxy = plugin_proxy.getProxy();
} else {
plugin_proxy = null;
}
try {
if (force_no_proxy) {
AEProxySelectorFactory.getSelector().startNoProxy();
}
if (auth_supplied) {
SESecurityManager.setPasswordHandler(url, this);
}
boolean dh_hack = false;
boolean internal_error_hack = false;
SSLSocketFactory ssl_socket_factory = null;
for (int connect_loop = 0; connect_loop < 2; connect_loop++) {
try {
HttpURLConnection con;
if (url.getProtocol().equalsIgnoreCase("https")) {
// see ConfigurationChecker for SSL client defaults
HttpsURLConnection ssl_con = (HttpsURLConnection) openConnection(force_proxy, url);
if (ssl_socket_factory != null) {
ssl_con.setSSLSocketFactory(ssl_socket_factory);
}
if (!internal_error_hack) {
ssl_con.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String host, SSLSession session) {
return (true);
}
});
}
if (plugin_proxy != null) {
TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
final List<X509TrustManager> default_tms = new ArrayList<>();
if (tmf != null) {
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
default_tms.add((X509TrustManager) tm);
}
}
}
TrustManager[] tms_delegate = SESecurityManager.getAllTrustingTrustManager(new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
List<X509Certificate> result = new ArrayList<>();
for (X509TrustManager tm : default_tms) {
result.addAll(Arrays.asList(tm.getAcceptedIssuers()));
}
return (result.toArray(new X509Certificate[result.size()]));
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager tm : default_tms) {
tm.checkClientTrusted(chain, authType);
}
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
for (X509TrustManager tm : default_tms) {
tm.checkServerTrusted(chain, authType);
}
}
});
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, tms_delegate, RandomUtils.SECURE_RANDOM);
SSLSocketFactory factory = sc.getSocketFactory();
ssl_con.setSSLSocketFactory(factory);
}
if (dh_hack) {
UrlUtils.DHHackIt(ssl_con);
}
if (internal_error_hack && plugin_proxy != null) {
String host = plugin_proxy.getURLHostRewrite();
UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
}
con = ssl_con;
} else {
con = (HttpURLConnection) openConnection(force_proxy, url);
}
con.setInstanceFollowRedirects(plugin_proxy == null);
if (plugin_proxy != null) {
con.setRequestProperty("HOST", plugin_proxy.getURLHostRewrite() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
}
con.setRequestMethod("HEAD");
ClientIDGenerator cidg = ClientIDManagerImpl.getSingleton().getGenerator();
if (cidg != null) {
Properties props = new Properties();
cidg.generateHTTPProperties(null, props);
String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
con.setRequestProperty("User-Agent", ua);
}
setRequestProperties(con, false);
try {
con.connect();
} catch (AEProxyFactory.UnknownHostException e) {
throw (new UnknownHostException(e.getMessage()));
}
int response = con.getResponseCode();
setProperty("URL_HTTP_Response", new Long(response));
if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
// cheap option for the moment
return (-1);
}
URL dest = url;
if (plugin_proxy != null) {
try {
dest = new URL(plugin_proxy.getTarget());
} catch (Throwable e) {
}
}
throw (new ResourceDownloaderException(this, "Error on connect for '" + trimForDisplay(dest) + "': " + Integer.toString(response) + " " + con.getResponseMessage()));
}
getRequestProperties(con);
ok = true;
return (UrlUtils.getContentLength(con));
} catch (SSLException e) {
String msg = Debug.getNestedExceptionMessage(e);
if (connect_loop < 3) {
boolean try_again = false;
if (msg.contains("DH keypair")) {
if (!dh_hack) {
dh_hack = true;
try_again = true;
}
} else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
if (!internal_error_hack) {
internal_error_hack = true;
try_again = true;
}
}
ssl_socket_factory = SESecurityManager.installServerCertificates(url);
if (ssl_socket_factory != null) {
// certificate has been installed
try_again = true;
}
if (try_again) {
continue;
}
}
throw (e);
} catch (IOException e) {
if (connect_loop == 0) {
URL retry_url = UrlUtils.getIPV4Fallback(url);
if (retry_url != null) {
url = retry_url;
continue;
}
}
throw (e);
}
}
throw (new ResourceDownloaderException(this, "Should never get here"));
} finally {
if (auth_supplied) {
SESecurityManager.setPasswordHandler(url, null);
}
if (force_no_proxy) {
AEProxySelectorFactory.getSelector().endNoProxy();
}
if (plugin_proxy != null) {
plugin_proxy.setOK(ok);
force_proxy = null;
}
}
} catch (java.net.MalformedURLException e) {
throw (new ResourceDownloaderException(this, "Exception while parsing URL '" + original_url + "':" + e.getMessage(), e));
} catch (java.net.UnknownHostException e) {
throw (new ResourceDownloaderException(this, "Exception while initializing download of '" + trimForDisplay(original_url) + "': Unknown Host '" + e.getMessage() + "'", e));
} catch (java.io.IOException e) {
throw (new ResourceDownloaderException(this, "I/O Exception while downloading '" + trimForDisplay(original_url) + "'", e));
}
} catch (Throwable e) {
ResourceDownloaderException rde;
if (e instanceof ResourceDownloaderException) {
rde = (ResourceDownloaderException) e;
} else {
Debug.out(e);
rde = new ResourceDownloaderException(this, "Unexpected error", e);
}
throw (rde);
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class UtilitiesImpl method getRSSFeed.
@Override
public RSSFeed getRSSFeed(URL feed_location) throws ResourceDownloaderException, SimpleXMLParserDocumentException {
String feed_str = feed_location.toExternalForm();
String lc_feed_str = feed_str.toLowerCase(Locale.US);
ResourceDownloader rd;
PluginProxy plugin_proxy = null;
try {
if (lc_feed_str.startsWith("tor:")) {
String target_resource = feed_str.substring(4);
try {
feed_location = new URL(target_resource);
} catch (MalformedURLException e) {
throw (new ResourceDownloaderException(e));
}
Map<String, Object> options = new HashMap<>();
options.put(AEProxyFactory.PO_PEER_NETWORKS, new String[] { AENetworkClassifier.AT_TOR });
plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + target_resource + "'", feed_location, options, true);
if (plugin_proxy == null) {
throw (new ResourceDownloaderException("No Tor plugin proxy available for '" + feed_str + "'"));
}
rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
} else {
if (AENetworkClassifier.categoriseAddress(feed_location.getHost()) != AENetworkClassifier.AT_PUBLIC) {
plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + feed_location + "'", feed_location, true);
if (plugin_proxy == null) {
throw (new ResourceDownloaderException("No Plugin proxy available for '" + feed_str + "'"));
}
rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
} else {
rd = getResourceDownloaderFactory().create(feed_location);
}
}
return (getRSSFeed(feed_location, rd));
} finally {
if (plugin_proxy != null) {
plugin_proxy.setOK(true);
}
}
}
use of com.biglybt.core.proxy.AEProxyFactory.PluginProxy in project BiglyBT by BiglySoftware.
the class ExternalSeedHTTPDownloaderRange method downloadSocket.
public void downloadSocket(String[] prop_names, String[] prop_values, int length, ExternalSeedHTTPDownloaderListener listener, boolean con_fail_is_perm_fail) throws ExternalSeedException {
Socket socket = null;
boolean connected = false;
PluginProxy plugin_proxy = null;
boolean proxy_ok = false;
try {
String output_header = "GET " + very_original_url.getPath() + "?" + very_original_url.getQuery() + " HTTP/1.1" + NL + "Host: " + very_original_url.getHost() + (very_original_url.getPort() == -1 ? "" : (":" + very_original_url.getPort())) + NL + "Accept: */*" + NL + "Connection: Close" + // if we want to support keep-alive we'll need to implement a socket cache etc.
NL + "User-Agent: " + user_agent + NL;
for (int i = 0; i < prop_names.length; i++) {
output_header += prop_names[i] + ":" + prop_values[i] + NL;
}
output_header += NL;
int time_remaining = listener.getPermittedTime();
URL original_url = very_original_url;
URL current_url = original_url;
Proxy current_proxy = null;
if (AENetworkClassifier.categoriseAddress(very_original_url.getHost()) != AENetworkClassifier.AT_PUBLIC) {
plugin_proxy = AEProxyFactory.getPluginProxy("webseed", original_url);
if (plugin_proxy != null) {
current_url = plugin_proxy.getURL();
current_proxy = plugin_proxy.getProxy();
}
}
if (time_remaining > 0) {
if (current_proxy == null) {
socket = new Socket();
} else {
socket = new Socket(current_proxy);
}
socket.connect(new InetSocketAddress(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort()), time_remaining);
} else {
if (current_proxy == null) {
socket = new Socket(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort());
} else {
socket = new Socket(current_proxy);
socket.connect(new InetSocketAddress(current_url.getHost(), current_url.getPort() == -1 ? current_url.getDefaultPort() : current_url.getPort()));
}
}
connected = true;
proxy_ok = true;
time_remaining = listener.getPermittedTime();
if (time_remaining < 0) {
throw (new IOException("Timeout during connect"));
} else if (time_remaining > 0) {
socket.setSoTimeout(time_remaining);
}
OutputStream os = socket.getOutputStream();
os.write(output_header.getBytes("ISO-8859-1"));
os.flush();
InputStream is = socket.getInputStream();
try {
String input_header = "";
while (true) {
byte[] buffer = new byte[1];
int len = is.read(buffer);
if (len < 0) {
throw (new IOException("input too short reading header"));
}
input_header += (char) buffer[0];
if (input_header.endsWith(NL + NL)) {
break;
}
}
// HTTP/1.1 403 Forbidden
int line_end = input_header.indexOf(NL);
if (line_end == -1) {
throw (new IOException("header too short"));
}
String first_line = input_header.substring(0, line_end);
StringTokenizer tok = new StringTokenizer(first_line, " ");
tok.nextToken();
int response = Integer.parseInt(tok.nextToken());
last_response = response;
last_response_retry_after_secs = -1;
String response_str = tok.nextToken();
if (response == HttpURLConnection.HTTP_ACCEPTED || response == HttpURLConnection.HTTP_OK || response == HttpURLConnection.HTTP_PARTIAL) {
byte[] buffer = null;
int buffer_pos = 0;
int buffer_len = 0;
int pos = 0;
while (pos < length) {
if (buffer == null) {
buffer = listener.getBuffer();
buffer_pos = listener.getBufferPosition();
buffer_len = listener.getBufferLength();
}
int to_read = buffer_len - buffer_pos;
int permitted = listener.getPermittedBytes();
if (permitted < to_read) {
to_read = permitted;
}
int len = is.read(buffer, buffer_pos, to_read);
if (len < 0) {
break;
}
listener.reportBytesRead(len);
pos += len;
buffer_pos += len;
if (buffer_pos == buffer_len) {
listener.done();
buffer = null;
buffer_pos = 0;
}
}
if (pos != length) {
String log_str;
if (buffer == null) {
log_str = "No buffer assigned";
} else {
log_str = new String(buffer, 0, buffer_pos > 64 ? 64 : buffer_pos);
}
throw (new ExternalSeedException("Connection failed: data too short - " + length + "/" + pos + " [last=" + log_str + "]"));
}
// System.out.println( "download length: " + pos );
} else if (response == 503) {
// webseed support for temp unavail - read the data
String data_str = "";
while (true) {
byte[] buffer = new byte[1];
int len = is.read(buffer);
if (len < 0) {
break;
}
data_str += (char) buffer[0];
}
last_response_retry_after_secs = Integer.parseInt(data_str);
throw (new IOException("Server overloaded"));
} else {
ExternalSeedException error = new ExternalSeedException("Connection failed: " + response_str);
error.setPermanentFailure(true);
throw (error);
}
} finally {
is.close();
}
} catch (IOException e) {
if (con_fail_is_perm_fail && !connected) {
ExternalSeedException error = new ExternalSeedException("Connection failed: " + e.getMessage());
error.setPermanentFailure(true);
throw (error);
} else {
String outcome = "Connection failed: " + Debug.getNestedExceptionMessage(e);
if (last_response_retry_after_secs >= 0) {
outcome += ", Retry-After: " + last_response_retry_after_secs + " seconds";
}
throw (new ExternalSeedException(outcome, e));
}
} catch (Throwable e) {
if (e instanceof ExternalSeedException) {
throw ((ExternalSeedException) e);
}
throw (new ExternalSeedException("Connection failed", e));
} finally {
if (socket != null) {
try {
socket.close();
} catch (Throwable e) {
}
}
if (plugin_proxy != null) {
plugin_proxy.setOK(proxy_ok);
}
}
}
Aggregations