diff --git a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java index 1a7df8ee5..76fd83f08 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/http/HttpConnectionManager.java @@ -11,8 +11,8 @@ import java.net.Proxy; import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -25,68 +25,86 @@ import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.TLSSocketFactory; -import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded; public class HttpConnectionManager extends AbstractConnectionManager { - public HttpConnectionManager(XmppConnectionService service) { - super(service); - } + private final List downloadConnections = new ArrayList<>(); + private final List uploadConnections = new ArrayList<>(); - private List downloadConnections = new CopyOnWriteArrayList<>(); - private List uploadConnections = new CopyOnWriteArrayList<>(); + public HttpConnectionManager(XmppConnectionService service) { + super(service); + } - public HttpDownloadConnection createNewDownloadConnection(Message message) { - return this.createNewDownloadConnection(message, false); - } + public static Proxy getProxy() throws IOException { + return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByAddress(new byte[]{127, 0, 0, 1}), 8118)); + } - public HttpDownloadConnection createNewDownloadConnection(Message message, boolean interactive) { - HttpDownloadConnection connection = new HttpDownloadConnection(this); - connection.init(message,interactive); - this.downloadConnections.add(connection); - return connection; - } + public void createNewDownloadConnection(Message message) { + this.createNewDownloadConnection(message, false); + } - public void createNewUploadConnection(Message message, boolean delay) { - HttpUploadConnection connection = new HttpUploadConnection(Method.determine(message.getConversation().getAccount()), this); - connection.init(message,delay); - this.uploadConnections.add(connection); - } + public void createNewDownloadConnection(final Message message, boolean interactive) { + synchronized (this.downloadConnections) { + for(HttpDownloadConnection connection : this.downloadConnections) { + if (connection.getMessage() == message) { + Log.d(Config.LOGTAG, message.getConversation().getAccount().getJid().asBareJid() + ": download already in progress"); + return; + } + } + final HttpDownloadConnection connection = new HttpDownloadConnection(message, this); + connection.init(interactive); + this.downloadConnections.add(connection); + } + } - public boolean checkConnection(Message message) { - final Account account = message.getConversation().getAccount(); - final URL url = message.getFileParams().url; - if (url.getProtocol().equalsIgnoreCase(P1S3UrlStreamHandler.PROTOCOL_NAME) && account.getStatus() != Account.State.ONLINE) { - return false; - } - return mXmppConnectionService.hasInternetConnection(); - } + public void createNewUploadConnection(final Message message, boolean delay) { + synchronized (this.uploadConnections) { + for (HttpUploadConnection connection : this.uploadConnections) { + if (connection.getMessage() == message) { + Log.d(Config.LOGTAG, message.getConversation().getAccount().getJid().asBareJid() + ": upload already in progress"); + return; + } + } + HttpUploadConnection connection = new HttpUploadConnection(message, Method.determine(message.getConversation().getAccount()), this); + connection.init(delay); + this.uploadConnections.add(connection); + } + } - public void finishConnection(HttpDownloadConnection connection) { - this.downloadConnections.remove(connection); - } + public boolean checkConnection(Message message) { + final Account account = message.getConversation().getAccount(); + final URL url = message.getFileParams().url; + if (url.getProtocol().equalsIgnoreCase(P1S3UrlStreamHandler.PROTOCOL_NAME) && account.getStatus() != Account.State.ONLINE) { + return false; + } + return mXmppConnectionService.hasInternetConnection(); + } - public void finishUploadConnection(HttpUploadConnection httpUploadConnection) { - this.uploadConnections.remove(httpUploadConnection); - } + void finishConnection(HttpDownloadConnection connection) { + synchronized (this.downloadConnections) { + this.downloadConnections.remove(connection); + } + } - public void setupTrustManager(final HttpsURLConnection connection, final boolean interactive) { - final X509TrustManager trustManager; - final HostnameVerifier hostnameVerifier = mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier(), interactive); - if (interactive) { - trustManager = mXmppConnectionService.getMemorizingTrustManager().getInteractive(); - } else { - trustManager = mXmppConnectionService.getMemorizingTrustManager().getNonInteractive(); - } - try { - final SSLSocketFactory sf = new TLSSocketFactory(new X509TrustManager[]{trustManager}, mXmppConnectionService.getRNG()); - connection.setSSLSocketFactory(sf); - connection.setHostnameVerifier(hostnameVerifier); - } catch (final KeyManagementException | NoSuchAlgorithmException ignored) { - } - } + void finishUploadConnection(HttpUploadConnection httpUploadConnection) { + synchronized (this.uploadConnections) { + this.uploadConnections.remove(httpUploadConnection); + } + } - public static Proxy getProxy() throws IOException { - return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByAddress(new byte[]{127,0,0,1}), 8118)); - } + void setupTrustManager(final HttpsURLConnection connection, final boolean interactive) { + final X509TrustManager trustManager; + final HostnameVerifier hostnameVerifier = mXmppConnectionService.getMemorizingTrustManager().wrapHostnameVerifier(new StrictHostnameVerifier(), interactive); + if (interactive) { + trustManager = mXmppConnectionService.getMemorizingTrustManager().getInteractive(); + } else { + trustManager = mXmppConnectionService.getMemorizingTrustManager().getNonInteractive(); + } + try { + final SSLSocketFactory sf = new TLSSocketFactory(new X509TrustManager[]{trustManager}, mXmppConnectionService.getRNG()); + connection.setSSLSocketFactory(sf); + connection.setHostnameVerifier(hostnameVerifier); + } catch (final KeyManagementException | NoSuchAlgorithmException ignored) { + } + } } diff --git a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java index 60b49bf89..74f8edebb 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java @@ -39,7 +39,7 @@ public class HttpDownloadConnection implements Transferable { private XmppConnectionService mXmppConnectionService; private URL mUrl; - private Message message; + private final Message message; private DownloadableFile file; private int mStatus = Transferable.STATUS_UNKNOWN; private boolean acceptedAutomatically = false; @@ -48,7 +48,8 @@ public class HttpDownloadConnection implements Transferable { private boolean canceled = false; private Method method = Method.HTTP_UPLOAD; - HttpDownloadConnection(HttpConnectionManager manager) { + HttpDownloadConnection(Message message, HttpConnectionManager manager) { + this.message = message; this.mHttpConnectionManager = manager; this.mXmppConnectionService = manager.getXmppConnectionService(); this.mUseTor = mXmppConnectionService.useTorToConnect(); @@ -68,12 +69,7 @@ public class HttpDownloadConnection implements Transferable { } } - public void init(Message message) { - init(message, false); - } - - public void init(Message message, boolean interactive) { - this.message = message; + public void init(boolean interactive) { this.message.setTransferable(this); try { if (message.hasFileOnRemoteHost()) { @@ -195,6 +191,10 @@ public class HttpDownloadConnection implements Transferable { return this.mProgress; } + public Message getMessage() { + return message; + } + private class FileSizeChecker implements Runnable { private final boolean interactive; diff --git a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java index a38bfd906..eba40054a 100644 --- a/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java +++ b/src/main/java/eu/siacs/conversations/http/HttpUploadConnection.java @@ -43,14 +43,15 @@ public class HttpUploadConnection implements Transferable { private boolean cancelled = false; private boolean delayed = false; private DownloadableFile file; - private Message message; + private final Message message; private String mime; private SlotRequester.Slot slot; private byte[] key = null; private long transmitted = 0; - public HttpUploadConnection(Method method, HttpConnectionManager httpConnectionManager) { + public HttpUploadConnection(Message message, Method method, HttpConnectionManager httpConnectionManager) { + this.message = message; this.method = method; this.mHttpConnectionManager = httpConnectionManager; this.mXmppConnectionService = httpConnectionManager.getXmppConnectionService(); @@ -87,13 +88,16 @@ public class HttpUploadConnection implements Transferable { } private void fail(String errorMessage) { - mHttpConnectionManager.finishUploadConnection(this); - message.setTransferable(null); + finish(); mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED, cancelled ? Message.ERROR_MESSAGE_CANCELLED : errorMessage); } - public void init(Message message, boolean delay) { - this.message = message; + private void finish() { + mHttpConnectionManager.finishUploadConnection(this); + message.setTransferable(null); + } + + public void init(boolean delay) { final Account account = message.getConversation().getAccount(); this.file = mXmppConnectionService.getFileBackend().getFile(message, false); if (message.getEncryption() == Message.ENCRYPTION_PGP || message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { @@ -211,7 +215,7 @@ public class HttpUploadConnection implements Transferable { } mXmppConnectionService.getFileBackend().updateFileParams(message, get); mXmppConnectionService.getFileBackend().updateMediaScanner(file); - message.setTransferable(null); + finish(); message.setCounterpart(message.getConversation().getJid().asBareJid()); mXmppConnectionService.resendMessage(message, delayed); } else { @@ -231,4 +235,8 @@ public class HttpUploadConnection implements Transferable { WakeLockHelper.release(wakeLock); } } + + public Message getMessage() { + return message; + } }