also reply with direct connections on response

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/Config.java                            |  1 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java      | 34 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java | 29 
3 files changed, 40 insertions(+), 24 deletions(-)

Detailed changes

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

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<JingleCandidate> 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<JingleCandidate> 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<String> 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());

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();