diff --git a/src/megabasterd/ChunkDownloader.java b/src/megabasterd/ChunkDownloader.java index 10574c43a..985cff702 100644 --- a/src/megabasterd/ChunkDownloader.java +++ b/src/megabasterd/ChunkDownloader.java @@ -115,7 +115,7 @@ public class ChunkDownloader implements Runnable, SecureSingleThreadNotifiable { _download.setUse_smart_proxy(false); } - if (httpclient == null || error || (_download.getMain_panel().isUse_smart_proxy() && _download.isUse_smart_proxy())) { + if (httpclient == null || error || _download.getMain_panel().isUse_smart_proxy()) { if (error509 && !_download.isUse_smart_proxy()) { _download.setUse_smart_proxy(true); diff --git a/src/megabasterd/KissVideoStreamServer.java b/src/megabasterd/KissVideoStreamServer.java index 75bf038ea..14ac09401 100644 --- a/src/megabasterd/KissVideoStreamServer.java +++ b/src/megabasterd/KissVideoStreamServer.java @@ -17,12 +17,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.logging.Level; import static java.util.logging.Level.SEVERE; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.crypto.CipherInputStream; +import static megabasterd.Download.WATCHDOG_SMART_PROXY_TIMEOUT; import static megabasterd.MainPanel.*; import static megabasterd.MiscTools.*; import org.apache.http.HttpStatus; @@ -35,7 +37,7 @@ public final class KissVideoStreamServer implements HttpHandler, SecureSingleThr public static final int WORKER_STATUS_STREAM = 0x02; public static final int WORKER_STATUS_RETRY = 0x03; public static final int WORKER_STATUS_EXIT = 0x04; - public static final int WORKERS = 4; + public static final int WORKERS = 8; private final MainPanel _main_panel; private final ConcurrentHashMap> _link_cache; @@ -43,6 +45,10 @@ public final class KissVideoStreamServer implements HttpHandler, SecureSingleThr private final ContentType _ctype; private boolean _notified; private final Object _secure_notify_lock; + private volatile boolean _use_smart_proxy; + private volatile int _last_proxy_list_hashcode; + private final ConcurrentLinkedQueue _excluded_proxies; + private final Object _watchdog_lock; public KissVideoStreamServer(MainPanel panel) { _main_panel = panel; @@ -51,6 +57,60 @@ public final class KissVideoStreamServer implements HttpHandler, SecureSingleThr _ctype = new ContentType(); _notified = false; _secure_notify_lock = new Object(); + _use_smart_proxy = false; + _watchdog_lock = new Object(); + _excluded_proxies = new ConcurrentLinkedQueue<>(); + _last_proxy_list_hashcode = -1; + } + + private void _start_smart_proxy_watchdog() { + + THREAD_POOL.execute(new Runnable() { + + @Override + public void run() { + + while (true) { + + try { + + if (_use_smart_proxy) { + + _use_smart_proxy = false; + + int proxy_list_hashcode = getMain_panel().getProxy_manager().getProxy_list().hashCode(); + + if (_last_proxy_list_hashcode != proxy_list_hashcode) { + + _last_proxy_list_hashcode = proxy_list_hashcode; + _excluded_proxies.clear(); + Logger.getLogger(KissVideoStreamServer.class.getName()).log(Level.INFO, "{0} SmartProxy excluded list cleared!", new Object[]{Thread.currentThread().getName()}); + + } + } + + synchronized (_watchdog_lock) { + _watchdog_lock.wait(WATCHDOG_SMART_PROXY_TIMEOUT * 1000); + } + + } catch (InterruptedException ex) { + Logger.getLogger(KissVideoStreamServer.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + }); + } + + public ConcurrentLinkedQueue getExcluded_proxies() { + return _excluded_proxies; + } + + public boolean isUse_smart_proxy() { + return _use_smart_proxy; + } + + public void setUse_smart_proxy(boolean _use_smart_proxy) { + this._use_smart_proxy = _use_smart_proxy; } public MainPanel getMain_panel() { @@ -97,6 +157,9 @@ public final class KissVideoStreamServer implements HttpHandler, SecureSingleThr } public void start(int port, String context) throws IOException { + + _start_smart_proxy_watchdog(); + swingReflectionInvoke("setForeground", _main_panel.getView().getKiss_server_status(), new Color(0, 128, 0)); swingReflectionInvoke("setText", _main_panel.getView().getKiss_server_status(), "Stream server running on localhost:" + STREAMER_PORT + " (Waiting for request...)"); diff --git a/src/megabasterd/MainPanel.java b/src/megabasterd/MainPanel.java index 004b9afcc..c0d24a4a1 100644 --- a/src/megabasterd/MainPanel.java +++ b/src/megabasterd/MainPanel.java @@ -45,7 +45,7 @@ import org.apache.http.auth.UsernamePasswordCredentials; */ public final class MainPanel { - public static final String VERSION = "2.45"; + public static final String VERSION = "2.46"; public static final int THROTTLE_SLICE_SIZE = 16 * 1024; public static final int DEFAULT_BYTE_BUFFER_SIZE = 16 * 1024; public static final int STREAMER_PORT = 1337; diff --git a/src/megabasterd/StreamChunkDownloader.java b/src/megabasterd/StreamChunkDownloader.java index f13d7a625..8b1d84d7f 100644 --- a/src/megabasterd/StreamChunkDownloader.java +++ b/src/megabasterd/StreamChunkDownloader.java @@ -12,7 +12,6 @@ import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; import static megabasterd.MainPanel.*; -import static megabasterd.MiscTools.*; import org.apache.http.HttpStatus; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; @@ -43,11 +42,15 @@ public class StreamChunkDownloader implements Runnable { Logger.getLogger(getClass().getName()).log(Level.INFO, "{0} Worker [{1}]: let''s do some work!", new Object[]{Thread.currentThread().getName(), _id}); - try (CloseableHttpClient httpclient = getApacheKissHttpClient()) { + CloseableHttpClient httpclient = null; + + try { String url = _chunkwriter.getUrl(); boolean error = false; + boolean error509 = false; + String current_proxy = null; long offset = -1; @@ -60,6 +63,44 @@ public class StreamChunkDownloader implements Runnable { _chunkwriter.secureWait(); } + if (_chunkwriter.getServer().isUse_smart_proxy() && !_chunkwriter.getServer().getMain_panel().isUse_smart_proxy()) { + + _chunkwriter.getServer().setUse_smart_proxy(false); + } + + if (httpclient == null || error || _chunkwriter.getServer().isUse_smart_proxy()) { + + if (error509 && !_chunkwriter.getServer().isUse_smart_proxy()) { + _chunkwriter.getServer().setUse_smart_proxy(true); + } + + if (_chunkwriter.getServer().isUse_smart_proxy() && !MainPanel.isUse_proxy()) { + + if (error && current_proxy != null) { + + Logger.getLogger(getClass().getName()).log(Level.WARNING, "{0} Worker [{1}]: excluding proxy -> {2}", new Object[]{Thread.currentThread().getName(), _id, current_proxy}); + + _chunkwriter.getServer().getExcluded_proxies().add(current_proxy); + } + + current_proxy = _chunkwriter.getServer().getMain_panel().getProxy_manager().getRandomProxy(_chunkwriter.getServer().getExcluded_proxies()); + + if (httpclient != null) { + try { + httpclient.close(); + } catch (IOException ex) { + Logger.getLogger(StreamChunkDownloader.class.getName()).log(Level.SEVERE, null, ex); + } + } + + httpclient = current_proxy != null ? MiscTools.getApacheKissHttpClientSmartProxy(current_proxy) : MiscTools.getApacheKissHttpClient(); + + } else if (httpclient == null) { + + httpclient = MiscTools.getApacheKissHttpClient(); + } + } + if (!error) { offset = _chunkwriter.nextOffset(); @@ -98,8 +139,8 @@ public class StreamChunkDownloader implements Runnable { error = true; if (http_status == 509) { - _exit = true; - _chunkwriter.setExit(true); + + error509 = true; } } else { @@ -144,6 +185,16 @@ public class StreamChunkDownloader implements Runnable { Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex); } catch (ChunkInvalidException | InterruptedException ex) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + Logger.getLogger(StreamChunkDownloader.class.getName()).log(Level.SEVERE, null, ex); + } finally { + if (httpclient != null) { + try { + httpclient.close(); + } catch (IOException ex) { + Logger.getLogger(StreamChunkDownloader.class.getName()).log(Level.SEVERE, null, ex); + } + } } _chunkwriter.secureNotifyAll(); diff --git a/src/megabasterd/StreamChunkWriter.java b/src/megabasterd/StreamChunkWriter.java index 3ab6cf7d9..9e9b4df8d 100644 --- a/src/megabasterd/StreamChunkWriter.java +++ b/src/megabasterd/StreamChunkWriter.java @@ -72,6 +72,10 @@ public class StreamChunkWriter implements Runnable, SecureMultiThreadNotifiable return _chunk_queue; } + public KissVideoStreamServer getServer() { + return _server; + } + @Override public void run() {