diff options
author | Christian Schneppe <christian@pix-art.de> | 2019-09-03 19:50:42 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2019-09-03 19:50:42 +0200 |
commit | 71e4bcf9cb807e2f3954a5e968a44a409aaeebd7 (patch) | |
tree | e1f92e73467a3c5cad8da7943fbc8dbf0eb1f6be /src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java | |
parent | edcfdb974dc544c0e79e457f50c12e5942619251 (diff) |
bare minimum direct connections
Diffstat (limited to 'src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java')
-rw-r--r-- | src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java index 7538ad980..f1b527b99 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java @@ -6,9 +6,12 @@ import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; +import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -30,6 +33,7 @@ public class JingleSocks5Transport extends JingleTransport { private InputStream inputStream; private boolean isEstablished = false; private boolean activated = false; + private ServerSocket serverSocket; private Socket socket; JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) { @@ -57,6 +61,88 @@ public class JingleSocks5Transport extends JingleTransport { } messageDigest.reset(); this.destination = CryptoHelper.bytesToHex(messageDigest.digest(destBuilder.toString().getBytes())); + if (candidate.isOurs() && candidate.getType() == JingleCandidate.TYPE_DIRECT) { + createServerSocket(); + } + } + + private void createServerSocket() { + try { + serverSocket = new ServerSocket(); + serverSocket.bind(new InetSocketAddress(InetAddress.getByName(candidate.getHost()), candidate.getPort())); + new Thread(() -> { + try { + final Socket socket = serverSocket.accept(); + new Thread(() -> { + try { + acceptIncomingSocketConnection(socket); + } catch (IOException e) { + Log.d(Config.LOGTAG, "unable to read from socket", e); + + } + }).start(); + } catch (IOException e) { + if (!serverSocket.isClosed()) { + Log.d(Config.LOGTAG, "unable to accept socket", e); + } + } + }).start(); + } catch (IOException 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(); + inputStream.read(authBegin); + if (authBegin[0] != 0x5) { + socket.close(); + } + short methodCount = authBegin[1]; + byte[] methods = new byte[methodCount]; + inputStream.read(methods); + if (SocksSocketFactory.contains((byte) 0x00, methods)) { + outputStream.write(new byte[]{0x05, 0x00}); + } else { + 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]; + inputStream.read(destination); + 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)) { + responseHeader = new byte[]{0x05, 0x00, 0x00, 0x03}; + success = true; + } else { + responseHeader = new byte[]{0x05, 0x04, 0x00, 0x03}; + success = false; + } + response.put(responseHeader); + response.put((byte) destination.length); + response.put(destination); + response.putShort((short) port); + outputStream.write(response.array()); + outputStream.flush(); + if (success) { + this.socket = socket; + this.inputStream = inputStream; + this.outputStream = outputStream; + this.isEstablished = true; + } + } else { + socket.close(); + } } public void connect(final OnTransportConnected callback) { @@ -72,7 +158,9 @@ public class JingleSocks5Transport extends JingleTransport { } inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); + socket.setSoTimeout(5000); SocksSocketFactory.createSocksConnection(socket, destination, 0); + socket.setSoTimeout(0); isEstablished = true; callback.established(); } catch (IOException e) { @@ -183,6 +271,7 @@ public class JingleSocks5Transport extends JingleTransport { FileBackend.close(inputStream); FileBackend.close(outputStream); FileBackend.close(socket); + FileBackend.close(serverSocket); } public boolean isEstablished() { |