Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ice4j 3.0 does not generate the IPv4 srflx candidate when android device APN is set to IPv4/IPv6 #255

Open
cmeng-git opened this issue Mar 12, 2022 · 3 comments

Comments

@cmeng-git
Copy link

See https://sanctum9.wordpress.com/2019/03/15/switch-to-ipv6-on-android/ on how to change network APN on android device.

The problem is observed with android device Note-10+ when the network APN is set to both 'IPv4/IPv6' (default);
The observation is performed on ice4j v3.0-55-g32a8aad on aTalk between Note-10 and SM-J730GM android devices. The HostCandidateHarvester#harvest() returns 3 host candidates containing an IPv6 public address.

2022-03-13 07:05:47.138 15183-15469/org.atalk.android I/aTalk: [245] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:1 1 udp 2130706431 2401:7400:4005:e3d9:1:1:9694:173e 5000 typ host
2022-03-13 07:05:47.158 15183-15469/org.atalk.android I/aTalk: [245] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:2 1 udp 2130706431 10.134.146.187 5000 typ host
2022-03-13 07:05:47.179 15183-15469/org.atalk.android I/aTalk: [245] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:3 1 udp 2113932031 10.170.32.102 5000 typ host

when this happen, the jingle:transports:ice-udp stanza contains only the following candidates with srflx candidate missing.
Because of the missing srflx candidate, the call setup failed.

<candidate port='58979' foundation='363454872' component='1' priority='2122262783' type='host' generation='0' protocol='udp' ip='2401:7400:4000:2e4a:1:2:93f1:b634' id='e49ea0a0-87e9-46a1-9c2e-1666b6ce8e32'/>
<candidate port='53151' foundation='2382162603' component='1' priority='2122194687' type='host' generation='0' protocol='udp' ip='10.142.116.152' id='97f487cc-5eb7-43a2-addf-9c2f4e782553'/>
<candidate rel-port='53151' port='53151' foundation='842163049' component='1' priority='1685987071' type='srflx' generation='0' protocol='udp' ip='119.56.101.12' rel-addr='10.142.116.152' id='f5b8f308-5810-49b5-bc14-f4d0d25953fc'/>
<candidate rel-port='53151' port='50438' foundation='1623785525' component='1' priority='41820671' type='relay' generation='0' protocol='udp' ip='42.60.77.13' rel-addr='119.56.101.12' id='3527fcc4-c91b-48f2-bce6-5bc283c320ef'/>
<candidate rel-port='53629' port='55128' foundation='776666309' component='1' priority='25042943' type='relay' generation='0' protocol='udp' ip='42.60.77.13' rel-addr='119.56.101.12' id='51efb2b2-fe49-4c15-ae80-a00a02d21617'/>

Not sure if there is such thing as IPv6 srflx candidate; or even work on android device that supports only IPv4 address if so.
Running conversations on Note-10+, it sends all the above candidates, and also the srflx candidate with IPv4 public address i.e.

<candidate foundation='3' component='1' protocol='udp' priority='1677724415' generation='0' id='11' ip='119.56.100.180' port='5002' type='srflx' rel-addr='10.143.27.57' rel-port='5002' network='0'/>

However when network APN is set to IPv4 only; then host candidates and jingle:transports:ice-udp contents are captured as below.
It is found that the transport candidate now contains the candidate type srflx, then the call setup is successfully.

2022-03-13 07:05:47.158 15183-15469/org.atalk.android I/aTalk: [245] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:1 1 udp 2130706431 10.134.146.187 5000 typ host
2022-03-13 07:05:47.179 15183-15469/org.atalk.android I/aTalk: [245] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:2 1 udp 2113932031 10.170.32.102 5000 typ host
<candidate foundation='1' component='1' protocol='udp' priority='2130706431' generation='0' id='9' ip='10.143.27.57' port='5002' type='host' network='0'/>
<candidate foundation='2' component='1' protocol='udp' priority='2130706431' generation='0' id='10' ip='10.170.32.102' port='5002' type='host' network='0'/>
<candidate foundation='3' component='1' protocol='udp' priority='1677724415' generation='0' id='11' ip='119.56.100.180' port='5002' type='srflx' rel-addr='10.143.27.57' rel-port='5002' network='0'/>
<candidate foundation='4' component='1' protocol='udp' priority='2815' generation='0' id='12' ip='42.60.77.13' port='50446' type='relay' network='0'/>
@cmeng-git
Copy link
Author

After further investigation, below are my findings that give rise to the problems:

When the android mobile APN is set to IPv4/IPv6, it is found that all the user defined STUN servers FQDN host names are also resolved to IPv6 addresses. Therefore with the below 3 discovered Host candidates, except for the first IPv6 candidate, the user defined STUN servers are not reachable with the other two IPv4 candidates.

2022-03-14 15:13:32.322 6643-7172/org.atalk.android I/aTalk: [239] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:1 1 udp 2130706431 2401:7400:4004:3b9f:1:2:9ce8:6fc8 5000 typ host
2022-03-14 15:13:32.324 6643-7172/org.atalk.android I/aTalk: [239] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:2 1 udp 2130706431 10.135.40.28 5000 typ host
2022-03-14 15:13:32.327 6643-7172/org.atalk.android I/aTalk: [239] org.ice4j.ice.harvest.HostCandidateHarvester.log() Host candidate added: candidate:3 1 udp 2113932031 10.170.32.102 5000 typ host

However the STUN server returns a redundant srflx candidate on STUN request for the first IPv6 public address, hence it is discarded. Currently, the problem can be resolved when the user entered the STUN server with an actual IP address e.g. STUN harvester(srvr: 172.217.213.127:19302/udp).

No sure if there is any way to force android device to return both IPv4 and IPv6 addresses for a user defined FQDN STUN host name; when the device mobile APN = IPv4/IPv6.

Found that android chrome browser is able to show both IPv4 and IPv6 addresses for the device public IP.

@cmeng-git
Copy link
Author

Found the solution with implementing the following function in IceUdpTransportManager.

    /**
     * Generate a list of TransportAddress from the given hostname, port and transport.
     * The given host name is resolved into both IPv4 and IPv6 InetAddresses.
     *
     * Note: android InetAddress.getByName(hostname) returns the first IP found, any may be an IPv6 InetAddress;
     * if mobile network setting for APN=IPV4/IPv6 or APN=IPv6. This causes problem in STUN candidate harvest:
     * @see https://github.com/jitsi/ice4j/issues/255
     *
     * @param hostname the address itself
     * @param port the port number
     * @param transport the transport to use with this address.
     */
    protected List<TransportAddress> getTransportAddress(String hostname, int port, Transport transport)
    {
        List<TransportAddress> transportAddress = new ArrayList<>();
        try {
            // return all associated InetAddress in both IPv4 and IPv6 address
            InetAddress[] inetAddresses = InetAddress.getAllByName(hostname);
            for (InetAddress inetAddress : inetAddresses) {
                transportAddress.add(new TransportAddress(inetAddress, port, transport));
            }
        } catch (UnknownHostException e) {
            Timber.e("UnknownHostException: %s", e.getMessage());
        }
        return transportAddress;
    }

@NimbleDev
Copy link

Found the solution with implementing the following function in IceUdpTransportManager.

    /**
     * Generate a list of TransportAddress from the given hostname, port and transport.
     * The given host name is resolved into both IPv4 and IPv6 InetAddresses.
     *
     * Note: android InetAddress.getByName(hostname) returns the first IP found, any may be an IPv6 InetAddress;
     * if mobile network setting for APN=IPV4/IPv6 or APN=IPv6. This causes problem in STUN candidate harvest:
     * @see https://github.com/jitsi/ice4j/issues/255
     *
     * @param hostname the address itself
     * @param port the port number
     * @param transport the transport to use with this address.
     */
    protected List<TransportAddress> getTransportAddress(String hostname, int port, Transport transport)
    {
        List<TransportAddress> transportAddress = new ArrayList<>();
        try {
            // return all associated InetAddress in both IPv4 and IPv6 address
            InetAddress[] inetAddresses = InetAddress.getAllByName(hostname);
            for (InetAddress inetAddress : inetAddresses) {
                transportAddress.add(new TransportAddress(inetAddress, port, transport));
            }
        } catch (UnknownHostException e) {
            Timber.e("UnknownHostException: %s", e.getMessage());
        }
        return transportAddress;
    }

I've encountered the same problem in my self hosted jitsi. But in current JVB version, getTransportAddress can not be found any more. Did you upgrade your jvb and found the new solution?

Looing forward to your reply eagerly and thx a lot in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants