Check local IP first always to properly handle cases where we're behind a router that won't get UDP traffic back to us if we use the remote address

This commit is contained in:
Cameron Gutman 2014-10-07 23:01:39 -07:00
parent a5171a1701
commit ace1339811

View File

@ -1,11 +1,6 @@
package com.limelight.computers; package com.limelight.computers;
import java.net.Inet4Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -24,11 +19,8 @@ import com.limelight.nvstream.mdns.MdnsDiscoveryListener;
import android.app.Service; import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
@ -234,93 +226,6 @@ public class ComputerManagerService extends Service {
}; };
} }
private int getActiveNetworkType() {
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
if (activeNetworkInfo == null) {
return -1;
}
return activeNetworkInfo.getType();
}
private InterfaceAddress getActiveInterfaceAddress() {
String matchingPrefix;
switch (getActiveNetworkType())
{
case ConnectivityManager.TYPE_ETHERNET:
matchingPrefix = "eth";
break;
case ConnectivityManager.TYPE_WIFI:
matchingPrefix = "wlan";
break;
default:
// Must be on Ethernet or Wifi to consider that we can send large packets
return null;
}
// Try to find the interface that corresponds to the active network
try {
Enumeration<NetworkInterface> ifaceList = NetworkInterface.getNetworkInterfaces();
while (ifaceList.hasMoreElements()) {
NetworkInterface iface = ifaceList.nextElement();
// Look for an interface that matches the prefix we expect
if (iface.isUp() && iface.getName().startsWith(matchingPrefix)) {
// Find the IPv4 address for the interface
for (InterfaceAddress addr : iface.getInterfaceAddresses()) {
if (!(addr.getAddress() instanceof Inet4Address)) {
// Skip non-IPv4 addresses
continue;
}
// Found the right address on the right interface
return addr;
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
// We didn't find the interface or something else went wrong
return null;
}
private boolean isOnSameSubnet(InetAddress targetAddress, InetAddress localAddress, short networkPrefixLength) {
byte[] targetBytes = targetAddress.getAddress();
byte[] localBytes = localAddress.getAddress();
for (int byteIndex = 0; networkPrefixLength > 0; byteIndex++) {
byte target = targetBytes[byteIndex];
byte local = localBytes[byteIndex];
if (networkPrefixLength >= 8) {
// Do a full byte comparison
if (target != local) {
return false;
}
networkPrefixLength -= 8;
}
else {
target &= (byte)(0xFF << (8 - networkPrefixLength));
local &= (byte)(0xFF << (8 - networkPrefixLength));
// Do a masked comparison
if (target != local) {
return false;
}
networkPrefixLength = 0;
}
}
return true;
}
private ComputerDetails tryPollIp(InetAddress ipAddr) { private ComputerDetails tryPollIp(InetAddress ipAddr) {
try { try {
NvHTTP http = new NvHTTP(ipAddr, idManager.getUniqueId(), NvHTTP http = new NvHTTP(ipAddr, idManager.getUniqueId(),
@ -373,27 +278,8 @@ public class ComputerManagerService extends Service {
} }
private boolean doPollMachine(ComputerDetails details) { private boolean doPollMachine(ComputerDetails details) {
// Get the network type
int networkType = getActiveNetworkType();
switch (networkType) {
// We'll check local first on these if we find
// we're on the same subnet
case ConnectivityManager.TYPE_ETHERNET:
case ConnectivityManager.TYPE_WIFI:
InterfaceAddress ifaceAddr = getActiveInterfaceAddress();
if (ifaceAddr != null) {
if (isOnSameSubnet(details.localIp, ifaceAddr.getAddress(), ifaceAddr.getNetworkPrefixLength())) {
// It's on the same subnet, so poll local first
LimeLog.info("Machine looks local; trying local IP first");
return pollComputer(details, true); return pollComputer(details, true);
} }
}
// Fall through to remote first
default:
LimeLog.info("Machine looks remote; trying remote IP first");
return pollComputer(details, false);
}
}
private Runnable getPollingRunnable(final ComputerDetails details) { private Runnable getPollingRunnable(final ComputerDetails details) {
return new Runnable() { return new Runnable() {