Reputation: 456
InetAddress.getAllByName()
only receives a list of IPv4 addresses, even when java.net.preferIPv6Addresses
is set to true, on a NAT64 network, on iOS devices. The same code works as expected on an android connected to the same network.
This means in an ipv6 only network (as required by the Apple store) any application attempting to make a HttpURLConnection will fail, and will be rejected by Apple.
I am creating an app for iOS in Java, I connect to the server using HttpsURLConnection
and everything works fine until I test on an NAT64 network. The app is being rejected by the Apple review team, and so I am testing locally using an NAT64 network.
To create my NAT64 network I follow these steps: Supporting IPv6 DNS64/NAT64 Networks
HttpsURLConnection testConn = null;
try {
URL testUrl = new URL("https://google.com");
testConn = (HttpsURLConnection) testUrl.openConnection();
testConn.connect();
}catch (Exception e){
e.printStackTrace();
}finally {
if(testConn != null){
testConn.disconnect();
}
}
This code fails with a java.net.SocketException: Network is unreachable
while on my NAT64 network.
I have tried changing system properties:
System.setProperty("java.net.preferIPv4Stack", "false");
System.setProperty("java.net.preferIPv6Addresses", "true");
I have also tried setting the website to something other than our servers (as seen in the test code with google.com). I have also sniffed the packets from the wi-fi connection using wireshark, and the only traffic is a DNS request for google.com which does not seem to fail. Finally I have also tried moving back to a HttpURLConnection
in case the problems was to do with HTTPS.
Also worth noting is safari on the test iPhone can reach all of our servers and domains without trouble, and the device seems to have a stable and functional internet connection otherwise. The app also fails on my android device when it is connected to the same NAT64 network.
Setting System.setProperty("java.net.preferIPv6Addresses", "true");
solves the problem on android, so now the issue is isolated to my iPhone5 on the NAT64 network. My best guess at this stage is that the property is being set by another class and is being ignored. I have tried setting the property in a static initializer block at the top of my class, to no avail.
I used System.getProperty("java.net.preferIPv6Addresses")
and it returns true
on the iPhone5 so it's definitely being set, leaving me stumped again.
I dug into HttpsURLConnection
and it implements a PlainSocketImpl
class to handle its connection, which uses an InetAddress
. I decided to test an InetAddress
and when I call InetAddress.getByName("google.com")
on the iPhone I get an ipv4 address, while on the android it is returning an ipv6 address. It seems that the property java.net.preferIPv6Addresses
is being ignored on iOS. I have tried updating the JDK to the latest version but this has not helped.
I have also just tried InetAddress.getAllByName("www.google.com")
and it only return IPv4 addresses on the iPhone. I would say this is clearly a DNS problem, but then why is it not an issue on an android connected to the same network?
So I now know what the issue is, yet have no idea how to fix it.
Upvotes: 1
Views: 1709
Reputation: 456
The solution was upgrading my app to run on the latest version of MAF.
Details:
Even though I had updated Eclipse and MAF to the latest version, my application was still using it's original MAF release as the target runtime. I discovered this by viewing my target SDK's and realizing I could not change the runtime verison.
To update I had to create a new project, making sure to set the target runtime to the latest version of MAF. I then migrated my code to this new project, and was able to successfully run my app under an IPv6 only network.
(at the time of writing MAF 2.3.2 was the latest version available for Eclipse)
If there is a way to do this without creating a new project, I could not discover it.
Upvotes: 1