diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 89883a61e..a5b3ab720 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -101,6 +101,7 @@ public final class Config { public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb + public static final boolean USE_DIRECT_JINGLE_CANDIDATES = false; public static final boolean DISABLE_HTTP_UPLOAD = false; public static final boolean EXTENDED_SM_LOGGING = false; // log stanza counts public static final boolean BACKGROUND_STANZA_LOGGING = false; //log all stanzas that were received while the app is in background 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 a9ac6e7df..7e48ad666 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -171,7 +171,8 @@ public class JingleConnection implements Transferable { @Override public void failed() { - Log.d(Config.LOGTAG, "proxy activation failed"); + Log.d(Config.LOGTAG, account.getJid().asBareJid()+": proxy activation failed"); + //TODO: when initiating send fallback to ibb } }; @@ -303,14 +304,7 @@ public class JingleConnection implements Transferable { if (this.initialTransport == Transport.IBB) { this.sendInitRequest(); } else { - - final List directCandidates = DirectConnectionUtils.getLocalCandidates(account.getJid()); - for (JingleCandidate directCandidate : directCandidates) { - final JingleSocks5Transport socksConnection = new JingleSocks5Transport(this, directCandidate); - connections.put(directCandidate.getCid(), socksConnection); - candidates.add(directCandidate); - } - + gatherAndConnectDirectCandidates(); this.mJingleConnectionManager.getPrimaryCandidate(account, (success, candidate) -> { if (success) { final JingleSocks5Transport socksConnection = new JingleSocks5Transport(this, candidate); @@ -342,6 +336,24 @@ public class JingleConnection implements Transferable { } + private void gatherAndConnectDirectCandidates() { + final List directCandidates; + if (Config.USE_DIRECT_JINGLE_CANDIDATES) { + if (account.isOnion() || mXmppConnectionService.useTorToConnect()) { + directCandidates = Collections.emptyList(); + } else { + directCandidates = DirectConnectionUtils.getLocalCandidates(account.getJid()); + } + } else { + directCandidates = Collections.emptyList(); + } + for (JingleCandidate directCandidate : directCandidates) { + final JingleSocks5Transport socksConnection = new JingleSocks5Transport(this, directCandidate); + connections.put(directCandidate.getCid(), socksConnection); + candidates.add(directCandidate); + } + } + private void upgradeNamespace() { List features = getRemoteFeatures(); if (features.contains(Content.Version.FT_5.getNamespace())) { @@ -570,6 +582,7 @@ public class JingleConnection implements Transferable { } private void sendAcceptSocks() { + gatherAndConnectDirectCandidates(); this.mJingleConnectionManager.getPrimaryCandidate(this.account, (success, candidate) -> { final JinglePacket packet = bootstrapPacket("session-accept"); final Content content = new Content(contentCreator, contentName); @@ -600,7 +613,7 @@ public class JingleConnection implements Transferable { } }); } else { - Log.d(Config.LOGTAG, "did not find a primary candidate for ourself"); + Log.d(Config.LOGTAG, "did not find a primary candidate for ourselves"); content.socks5transport().setChildren(getCandidatesAsElements()); packet.setContent(content); sendJinglePacket(packet); @@ -762,6 +775,7 @@ public class JingleConnection implements Transferable { if (response.getType() != IqPacket.TYPE.RESULT) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": " + response.toString()); onProxyActivated.failed(); + //TODO send proxy-error } else { onProxyActivated.success(); sendProxyActivated(connection.getCandidate().getCid()); 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 2db161271..f0ee5c12e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -76,7 +76,7 @@ public class JingleSocks5Transport extends JingleTransport { try { acceptIncomingSocketConnection(socket); } catch (IOException e) { - Log.d(Config.LOGTAG,"unable to read from socket",e); + Log.d(Config.LOGTAG, "unable to read from socket", e); } }).start(); @@ -87,43 +87,43 @@ public class JingleSocks5Transport extends JingleTransport { } }).start(); } catch (IOException e) { - Log.d(Config.LOGTAG,"unable to bind server socket ",e); + Log.d(Config.LOGTAG, "unable to bind server socket ", e); } } private void acceptIncomingSocketConnection(Socket socket) throws IOException { Log.d(Config.LOGTAG, "accepted connection from " + socket.getInetAddress().getHostAddress()); - byte[] authBegin = new byte[2]; - InputStream inputStream = socket.getInputStream(); - OutputStream outputStream = socket.getOutputStream(); + final byte[] authBegin = new byte[2]; + final InputStream inputStream = socket.getInputStream(); + final OutputStream outputStream = socket.getOutputStream(); inputStream.read(authBegin); if (authBegin[0] != 0x5) { socket.close(); } - short methodCount = authBegin[1]; - byte[] methods = new byte[methodCount]; + final short methodCount = authBegin[1]; + final byte[] methods = new byte[methodCount]; inputStream.read(methods); if (SocksSocketFactory.contains((byte) 0x00, methods)) { - outputStream.write(new byte[]{0x05,0x00}); + outputStream.write(new byte[]{0x05, 0x00}); } else { - outputStream.write(new byte[]{0x05,(byte) 0xff}); + outputStream.write(new byte[]{0x05, (byte) 0xff}); } byte[] connectCommand = new byte[4]; inputStream.read(connectCommand); if (connectCommand[0] == 0x05 && connectCommand[1] == 0x01 && connectCommand[3] == 0x03) { int destinationCount = inputStream.read(); - byte[] destination = new byte[destinationCount]; + final byte[] destination = new byte[destinationCount]; inputStream.read(destination); - int port = inputStream.read(); + final int port = inputStream.read(); final String receivedDestination = new String(destination); - Log.d(Config.LOGTAG, "received destination " + receivedDestination + ":" + port + " - expected " + this.destination); final ByteBuffer response = ByteBuffer.allocate(7 + destination.length); final byte[] responseHeader; final boolean success; - if (receivedDestination.equals(this.destination)) { + if (receivedDestination.equals(this.destination) && this.socket == null) { responseHeader = new byte[]{0x05, 0x00, 0x00, 0x03}; success = true; } else { + Log.d(Config.LOGTAG,connection.getAccount().getJid().asBareJid()+": destination mismatch. received "+receivedDestination+" (expected "+this.destination+")"); responseHeader = new byte[]{0x05, 0x04, 0x00, 0x03}; success = false; } @@ -138,6 +138,7 @@ public class JingleSocks5Transport extends JingleTransport { this.inputStream = inputStream; this.outputStream = outputStream; this.isEstablished = true; + FileBackend.close(serverSocket); } } else { socket.close(); @@ -153,7 +154,7 @@ public class JingleSocks5Transport extends JingleTransport { } else { socket = new Socket(); SocketAddress address = new InetSocketAddress(candidate.getHost(), candidate.getPort()); - socket.connect(address, Config.SOCKET_TIMEOUT * 1000); + socket.connect(address, 5000); } inputStream = socket.getInputStream(); outputStream = socket.getOutputStream();