Smack 4.4.8: localAddresses values in Socks5Proxy remain unchanged when there is a change in the network connection

localAddresses in Sock5Proxy is used by Socks5 file transfer in jingle FT method. The values are initialised when user is first authenticated (JingleS5BTransportManager), basing on the device current active network connection e.g. WiFi. It is found that when the WiFi is disabled and network connection is made via the mobile network, the localAddresses are not being updated hence contained an invalid transport candidate i.e. intranet IP.

aTalk made the following source changes to fix the problem.

  1. JingleS5BTransportManager.java file
    a. Remove the condition resumed test in authenticated() method.
    public void authenticated(XMPPConnection connection, boolean resumed) {
        // if (!resumed)
        try {
            Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
            if (!socks5Proxy.isRunning()) {
                socks5Proxy.start();
            }

            localStreamHosts = queryLocalStreamHosts();
            availableStreamHosts = queryAvailableStreamHosts();
            Timber.w("On authenticated resumed: %s; %s\n%s", resumed, localStreamHosts, availableStreamHosts);
        } catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException |
                 XMPPException.XMPPErrorException e) {
            LOGGER.log(Level.WARNING, "Could not query available StreamHosts: " + e, e);
        }
    }

b. Override connectionClosedOnError to call connectionClosed.

    @Override
    public void connectionClosedOnError(Exception e) {
        connectionClosed();
    }
  1. Socks5Proxy
    a. set socks5Server to null in stop method.
    /**
     * Stops the local SOCKS5 proxy server. If it is not running this method does nothing.
     */
    public synchronized void stop() {
        if (!isRunning()) {
            return;
        }

        RUNNING_PROXIES.remove(this);

        CloseableUtil.maybeClose(this.serverSocket, LOGGER);

        if (this.serverThread != null && this.serverThread.isAlive()) {
            try {
                this.serverThread.interrupt();
                this.serverThread.join();
            }
            catch (InterruptedException e) {
                LOGGER.log(Level.WARNING, "SOCKS5 server thread termination was interrupted", e);
            }
        }
        this.serverThread = null;
        this.serverSocket = null;

        // Stop Sock5Proxy so a new localAddresses are retrieved on new authentication process.
        socks5Server = null;
    }

I think you want to use

for example like

https://bitbucket.org/projectmaxs/maxs/src/7663bb8af7a55cac93c724cd7e41e649f8972b55/transport-xmpp/src/org/projectmaxs/transport/xmpp/xmppservice/XMPPFileTransfer.java#lines-192:213

    Socks5Proxy() {
        this.serverProcess = new Socks5ServerProcess();

        allowAllConnections = false;

        Enumeration<NetworkInterface> networkInterfaces;
        try {
            networkInterfaces = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            throw new IllegalStateException(e);
        }
        Set<InetAddress> localAddresses = new HashSet<>();
        for (NetworkInterface networkInterface : Collections.list(networkInterfaces)) {
            List<InterfaceAddress> interfaceAddresses = networkInterface.getInterfaceAddresses();
            for (InterfaceAddress interfaceAddress : interfaceAddresses) {
                localAddresses.add(interfaceAddress.getAddress());
            }
        }
        if (localAddresses.isEmpty()) {
            throw new IllegalStateException("Could not determine any local internet address");
        }
        replaceLocalAddresses(localAddresses);
    }

The function replaceLocalAddresses(localAddresses) is being called when Socks5Proxy() is first started.

aTalk proposed fixes is to allow this Socks5Proxy init function to get call again whenever there is a change in the new network connection.

Not going into details implementation, your proposed solution seems only works on new WiFi connection, it does not take care when the device reverts to use mobile network.

aTalk proposed solution also takes care of other scenarios. i.e. when device connect to a roaming networks, where connected IPS networks hence IP’s may varies.

I have not tested whether the device connected IP address gets change when the device is moving from one mobile cell to another. If so aTalk proposed solution also take care of this situation.