From 783ed53d3a97276173fd752e5b7a19ac492189bc Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 1 Sep 2019 11:34:36 +0200 Subject: [PATCH] order canditates by priority before attempting to connect --- .../xmpp/jingle/JingleConnection.java | 12 +- .../xmpp/jingle/JingleSocks5Transport.java | 322 +++++++++--------- 2 files changed, 168 insertions(+), 166 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index d06c2469f..e229c11ed 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -11,6 +11,7 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; @@ -303,7 +304,7 @@ public class JingleConnection implements Transferable { if (this.initialTransport == Transport.IBB) { this.sendInitRequest(); } else if (this.candidates.size() > 0) { - this.sendInitRequest(); + this.sendInitRequest(); //TODO we will never get here? Can probably be removed } else { this.mJingleConnectionManager.getPrimaryCandidate(account, (success, candidate) -> { if (success) { @@ -635,7 +636,7 @@ public class JingleConnection implements Transferable { private boolean receiveAccept(JinglePacket packet) { if (this.mJingleStatus != JINGLE_STATUS_INITIATED) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": received out of order session-accept"); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received out of order session-accept"); return false; } this.mJingleStatus = JINGLE_STATUS_ACCEPTED; @@ -654,7 +655,7 @@ public class JingleConnection implements Transferable { this.ibbBlockSize = bs; } } catch (Exception e) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to parse block size in session-accept"); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in session-accept"); } } this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize); @@ -850,7 +851,7 @@ public class JingleConnection implements Transferable { this.ibbBlockSize = bs; } } catch (NumberFormatException e) { - Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to parse block size in transport-replace"); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in transport-replace"); } } this.transportId = packet.getJingleContent().getTransportId(); @@ -889,7 +890,7 @@ public class JingleConnection implements Transferable { this.ibbBlockSize = bs; } } catch (NumberFormatException e) { - Log.d(Config.LOGTAG, account.getJid().asBareJid()+": unable to parse block size in transport-accept"); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in transport-accept"); } } this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize); @@ -1087,6 +1088,7 @@ public class JingleConnection implements Transferable { } private void mergeCandidates(List candidates) { + Collections.sort(candidates, (a, b) -> Integer.compare(b.getPriority(), a.getPriority())); for (JingleCandidate c : candidates) { mergeCandidate(c); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java index 99c12ba3a..4181335f6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -22,177 +22,177 @@ import eu.siacs.conversations.utils.WakeLockHelper; import eu.siacs.conversations.xmpp.jingle.stanzas.Content; public class JingleSocks5Transport extends JingleTransport { - private JingleCandidate candidate; - private JingleConnection connection; - private String destination; - private OutputStream outputStream; - private InputStream inputStream; - private boolean isEstablished = false; - private boolean activated = false; - private Socket socket; + private final JingleCandidate candidate; + private final JingleConnection connection; + private final String destination; + private OutputStream outputStream; + private InputStream inputStream; + private boolean isEstablished = false; + private boolean activated = false; + private Socket socket; - JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) { - this.candidate = candidate; - this.connection = jingleConnection; - try { - MessageDigest mDigest = MessageDigest.getInstance("SHA-1"); - StringBuilder destBuilder = new StringBuilder(); - if (jingleConnection.getFtVersion() == Content.Version.FT_3) { - Log.d(Config.LOGTAG, this.connection.getAccount().getJid().asBareJid() + ": using session Id instead of transport Id for proxy destination"); - destBuilder.append(jingleConnection.getSessionId()); - } else { - destBuilder.append(jingleConnection.getTransportId()); - } - if (candidate.isOurs()) { - destBuilder.append(jingleConnection.getAccount().getJid()); - destBuilder.append(jingleConnection.getCounterPart()); - } else { - destBuilder.append(jingleConnection.getCounterPart()); - destBuilder.append(jingleConnection.getAccount().getJid()); - } - mDigest.reset(); - this.destination = CryptoHelper.bytesToHex(mDigest - .digest(destBuilder.toString().getBytes())); - } catch (NoSuchAlgorithmException e) { + JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) { + final MessageDigest messageDigest; + try { + messageDigest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + this.candidate = candidate; + this.connection = jingleConnection; + final StringBuilder destBuilder = new StringBuilder(); + if (jingleConnection.getFtVersion() == Content.Version.FT_3) { + Log.d(Config.LOGTAG, this.connection.getAccount().getJid().asBareJid() + ": using session Id instead of transport Id for proxy destination"); + destBuilder.append(jingleConnection.getSessionId()); + } else { + destBuilder.append(jingleConnection.getTransportId()); + } + if (candidate.isOurs()) { + destBuilder.append(jingleConnection.getAccount().getJid()); + destBuilder.append(jingleConnection.getCounterPart()); + } else { + destBuilder.append(jingleConnection.getCounterPart()); + destBuilder.append(jingleConnection.getAccount().getJid()); + } + messageDigest.reset(); + this.destination = CryptoHelper.bytesToHex(messageDigest.digest(destBuilder.toString().getBytes())); + } - } - } + public void connect(final OnTransportConnected callback) { + new Thread(() -> { + try { + final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect(); + if (useTor) { + socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(), candidate.getPort()); + } else { + socket = new Socket(); + SocketAddress address = new InetSocketAddress(candidate.getHost(), candidate.getPort()); + socket.connect(address, Config.SOCKET_TIMEOUT * 1000); + } + inputStream = socket.getInputStream(); + outputStream = socket.getOutputStream(); + SocksSocketFactory.createSocksConnection(socket, destination, 0); + isEstablished = true; + callback.established(); + } catch (IOException e) { + callback.failed(); + } + }).start(); - public void connect(final OnTransportConnected callback) { - new Thread(() -> { - try { - final boolean useTor = connection.getAccount().isOnion() || connection.getConnectionManager().getXmppConnectionService().useTorToConnect(); - if (useTor) { - socket = SocksSocketFactory.createSocketOverTor(candidate.getHost(), candidate.getPort()); - } else { - socket = new Socket(); - SocketAddress address = new InetSocketAddress(candidate.getHost(), candidate.getPort()); - socket.connect(address, Config.SOCKET_TIMEOUT * 1000); - } - inputStream = socket.getInputStream(); - outputStream = socket.getOutputStream(); - SocksSocketFactory.createSocksConnection(socket, destination, 0); - isEstablished = true; - callback.established(); - } catch (IOException e) { - callback.failed(); - } - }).start(); + } - } + public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { + new Thread(() -> { + InputStream fileInputStream = null; + final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId()); + try { + wakeLock.acquire(); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + fileInputStream = connection.getFileInputStream(); + if (fileInputStream == null) { + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create input stream"); + callback.onFileTransferAborted(); + return; + } + final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream); + long size = file.getExpectedSize(); + long transmitted = 0; + int count; + byte[] buffer = new byte[8192]; + while ((count = innerInputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, count); + digest.update(buffer, 0, count); + transmitted += count; + connection.updateProgress((int) ((((double) transmitted) / size) * 100)); + } + outputStream.flush(); + file.setSha1Sum(digest.digest()); + if (callback != null) { + callback.onFileTransmitted(file); + } + } catch (Exception e) { + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage()); + callback.onFileTransferAborted(); + } finally { + FileBackend.close(fileInputStream); + WakeLockHelper.release(wakeLock); + } + }).start(); - public void send(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { - new Thread(() -> { - InputStream fileInputStream = null; - final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId()); - try { - wakeLock.acquire(); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - digest.reset(); - fileInputStream = connection.getFileInputStream(); - if (fileInputStream == null) { - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create input stream"); - callback.onFileTransferAborted(); - return; - } - final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream); - long size = file.getExpectedSize(); - long transmitted = 0; - int count; - byte[] buffer = new byte[8192]; - while ((count = innerInputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, count); - digest.update(buffer, 0, count); - transmitted += count; - connection.updateProgress((int) ((((double) transmitted) / size) * 100)); - } - outputStream.flush(); - file.setSha1Sum(digest.digest()); - if (callback != null) { - callback.onFileTransmitted(file); - } - } catch (Exception e) { - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage()); - callback.onFileTransferAborted(); - } finally { - FileBackend.close(fileInputStream); - WakeLockHelper.release(wakeLock); - } - }).start(); + } - } + public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { + new Thread(() -> { + OutputStream fileOutputStream = null; + final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_" + connection.getSessionId()); + try { + wakeLock.acquire(); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + //inputStream.skip(45); + socket.setSoTimeout(30000); + fileOutputStream = connection.getFileOutputStream(); + if (fileOutputStream == null) { + callback.onFileTransferAborted(); + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create output stream"); + return; + } + double size = file.getExpectedSize(); + long remainingSize = file.getExpectedSize(); + byte[] buffer = new byte[8192]; + int count; + while (remainingSize > 0) { + count = inputStream.read(buffer); + if (count == -1) { + callback.onFileTransferAborted(); + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": file ended prematurely with " + remainingSize + " bytes remaining"); + return; + } else { + fileOutputStream.write(buffer, 0, count); + digest.update(buffer, 0, count); + remainingSize -= count; + } + connection.updateProgress((int) (((size - remainingSize) / size) * 100)); + } + fileOutputStream.flush(); + fileOutputStream.close(); + file.setSha1Sum(digest.digest()); + callback.onFileTransmitted(file); + } catch (Exception e) { + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage()); + callback.onFileTransferAborted(); + } finally { + WakeLockHelper.release(wakeLock); + FileBackend.close(fileOutputStream); + FileBackend.close(inputStream); + } + }).start(); + } - public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) { - new Thread(() -> { - OutputStream fileOutputStream = null; - final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_" + connection.getSessionId()); - try { - wakeLock.acquire(); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - digest.reset(); - //inputStream.skip(45); - socket.setSoTimeout(30000); - fileOutputStream = connection.getFileOutputStream(); - if (fileOutputStream == null) { - callback.onFileTransferAborted(); - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": could not create output stream"); - return; - } - double size = file.getExpectedSize(); - long remainingSize = file.getExpectedSize(); - byte[] buffer = new byte[8192]; - int count; - while (remainingSize > 0) { - count = inputStream.read(buffer); - if (count == -1) { - callback.onFileTransferAborted(); - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": file ended prematurely with " + remainingSize + " bytes remaining"); - return; - } else { - fileOutputStream.write(buffer, 0, count); - digest.update(buffer, 0, count); - remainingSize -= count; - } - connection.updateProgress((int) (((size - remainingSize) / size) * 100)); - } - fileOutputStream.flush(); - fileOutputStream.close(); - file.setSha1Sum(digest.digest()); - callback.onFileTransmitted(file); - } catch (Exception e) { - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage()); - callback.onFileTransferAborted(); - } finally { - WakeLockHelper.release(wakeLock); - FileBackend.close(fileOutputStream); - FileBackend.close(inputStream); - } - }).start(); - } + public boolean isProxy() { + return this.candidate.getType() == JingleCandidate.TYPE_PROXY; + } - public boolean isProxy() { - return this.candidate.getType() == JingleCandidate.TYPE_PROXY; - } + public boolean needsActivation() { + return (this.isProxy() && !this.activated); + } - public boolean needsActivation() { - return (this.isProxy() && !this.activated); - } + public void disconnect() { + FileBackend.close(inputStream); + FileBackend.close(outputStream); + FileBackend.close(socket); + } - public void disconnect() { - FileBackend.close(inputStream); - FileBackend.close(outputStream); - FileBackend.close(socket); - } + public boolean isEstablished() { + return this.isEstablished; + } - public boolean isEstablished() { - return this.isEstablished; - } + public JingleCandidate getCandidate() { + return this.candidate; + } - public JingleCandidate getCandidate() { - return this.candidate; - } - - public void setActivated(boolean activated) { - this.activated = activated; - } + public void setActivated(boolean activated) { + this.activated = activated; + } }