Convert address fields to strings to better manage DNS names

This commit is contained in:
Cameron Gutman 2017-09-09 13:39:20 -07:00
parent e7f92d3667
commit 8584bf1910
6 changed files with 63 additions and 58 deletions

View File

@ -7,7 +7,7 @@ import javax.crypto.SecretKey;
import com.limelight.nvstream.av.video.VideoDecoderRenderer; import com.limelight.nvstream.av.video.VideoDecoderRenderer;
public class ConnectionContext { public class ConnectionContext {
public InetAddress serverAddress; public String serverAddress;
public StreamConfiguration streamConfig; public StreamConfiguration streamConfig;
public NvConnectionListener connListener; public NvConnectionListener connListener;
public SecretKey riKey; public SecretKey riKey;

View File

@ -223,13 +223,7 @@ public class NvConnection {
String appName = context.streamConfig.getApp().getAppName(); String appName = context.streamConfig.getApp().getAppName();
try { context.serverAddress = host;
context.serverAddress = InetAddress.getByName(host);
} catch (UnknownHostException e) {
context.connListener.connectionTerminated(-1);
return;
}
context.connListener.stageStarting(appName); context.connListener.stageStarting(appName);
try { try {
@ -249,7 +243,7 @@ public class NvConnection {
// we must not invoke that functionality in parallel. // we must not invoke that functionality in parallel.
synchronized (MoonBridge.class) { synchronized (MoonBridge.class) {
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener); MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
MoonBridge.startConnection(context.serverAddress.getHostAddress(), MoonBridge.startConnection(context.serverAddress,
context.serverAppVersion, context.serverGfeVersion, context.serverAppVersion, context.serverGfeVersion,
context.negotiatedWidth, context.negotiatedHeight, context.negotiatedWidth, context.negotiatedHeight,
context.negotiatedFps, context.streamConfig.getBitrate(), context.negotiatedFps, context.streamConfig.getBitrate(),

View File

@ -16,8 +16,8 @@ public class ComputerDetails {
public Reachability reachability; public Reachability reachability;
public String name; public String name;
public UUID uuid; public UUID uuid;
public InetAddress localAddress; public String localAddress;
public InetAddress remoteAddress; public String remoteAddress;
public PairingManager.PairState pairState; public PairingManager.PairState pairState;
public String macAddress; public String macAddress;
public int runningGameId; public int runningGameId;

View File

@ -10,6 +10,8 @@ import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.Socket; import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.Principal; import java.security.Principal;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -46,7 +48,7 @@ import com.squareup.okhttp.ResponseBody;
public class NvHTTP { public class NvHTTP {
private String uniqueId; private String uniqueId;
private PairingManager pm; private PairingManager pm;
private InetAddress address; private String address;
public static final int HTTPS_PORT = 47984; public static final int HTTPS_PORT = 47984;
public static final int HTTP_PORT = 47989; public static final int HTTP_PORT = 47989;
@ -104,23 +106,21 @@ public class NvHTTP {
httpClientWithReadTimeout.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); httpClientWithReadTimeout.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
} }
public NvHTTP(InetAddress host, String uniqueId, String deviceName, LimelightCryptoProvider cryptoProvider) { public NvHTTP(String address, String uniqueId, String deviceName, LimelightCryptoProvider cryptoProvider) throws IOException {
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
this.address = host; this.address = address;
String safeAddress;
if (host instanceof Inet6Address) {
// RFC2732-formatted IPv6 address for use in URL
safeAddress = "["+host.getHostAddress()+"]";
}
else {
safeAddress = host.getHostAddress();
}
initializeHttpState(cryptoProvider); initializeHttpState(cryptoProvider);
this.baseUrlHttps = "https://" + safeAddress + ":" + HTTPS_PORT; try {
this.baseUrlHttp = "http://" + safeAddress + ":" + HTTP_PORT; // The URI constructor takes care of escaping IPv6 literals
this.baseUrlHttps = new URI("https", null, address, HTTPS_PORT, null, null, null).toString();
this.baseUrlHttp = new URI("http", null, address, HTTP_PORT, null, null, null).toString();
} catch (URISyntaxException e) {
// Encapsulate URISyntaxException into IOException for callers to handle more easily
throw new IOException(e);
}
this.pm = new PairingManager(this, cryptoProvider); this.pm = new PairingManager(this, cryptoProvider);
} }
@ -212,20 +212,17 @@ public class NvHTTP {
details.macAddress = getXmlString(serverInfo, "mac"); details.macAddress = getXmlString(serverInfo, "mac");
// If there's no LocalIP field, use the address we hit the server on // If there's no LocalIP field, use the address we hit the server on
String localIpStr = getXmlString(serverInfo, "LocalIP"); details.localAddress = getXmlString(serverInfo, "LocalIP");
if (localIpStr == null) { if (details.localAddress == null) {
localIpStr = address.getHostAddress(); details.localAddress = address;
} }
// If there's no ExternalIP field, use the address we hit the server on // If there's no ExternalIP field, use the address we hit the server on
String externalIpStr = getXmlString(serverInfo, "ExternalIP"); details.remoteAddress = getXmlString(serverInfo, "ExternalIP");
if (externalIpStr == null) { if (details.remoteAddress == null) {
externalIpStr = address.getHostAddress(); details.remoteAddress = address;
} }
details.localAddress = InetAddress.getByName(localIpStr);
details.remoteAddress = InetAddress.getByName(externalIpStr);
try { try {
details.pairState = Integer.parseInt(getXmlString(serverInfo, "PairStatus")) == 1 ? details.pairState = Integer.parseInt(getXmlString(serverInfo, "PairStatus")) == 1 ?
PairState.PAIRED : PairState.NOT_PAIRED; PairState.PAIRED : PairState.NOT_PAIRED;

View File

@ -1,12 +1,12 @@
package com.limelight.nvstream.mdns; package com.limelight.nvstream.mdns;
import java.net.InetAddress; import java.net.Inet4Address;
public class MdnsComputer { public class MdnsComputer {
private InetAddress ipAddr; private Inet4Address ipAddr;
private String name; private String name;
public MdnsComputer(String name, InetAddress addr) { public MdnsComputer(String name, Inet4Address addr) {
this.name = name; this.name = name;
this.ipAddr = addr; this.ipAddr = addr;
} }
@ -15,7 +15,7 @@ public class MdnsComputer {
return name; return name;
} }
public InetAddress getAddress() { public Inet4Address getAddress() {
return ipAddr; return ipAddr;
} }

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.DatagramPacket; import java.net.DatagramPacket;
import java.net.DatagramSocket; import java.net.DatagramSocket;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner; import java.util.Scanner;
import com.limelight.LimeLog; import com.limelight.LimeLog;
@ -17,28 +18,41 @@ public class WakeOnLanSender {
public static void sendWolPacket(ComputerDetails computer) throws IOException { public static void sendWolPacket(ComputerDetails computer) throws IOException {
DatagramSocket sock = new DatagramSocket(0); DatagramSocket sock = new DatagramSocket(0);
byte[] payload = createWolPayload(computer); byte[] payload = createWolPayload(computer);
// Try both remote and local addresses IOException lastException = null;
for (int i = 0; i < 2; i++) { boolean sentWolPacket = false;
InetAddress addr;
if (i == 0) {
addr = computer.localAddress;
}
else {
addr = computer.remoteAddress;
}
// Try all the ports for each address try {
// Try all resolved remote and local addresses
for (String unresolvedAddress : new String[] {computer.localAddress, computer.remoteAddress}) {
try {
for (InetAddress resolvedAddress : InetAddress.getAllByName(unresolvedAddress)) {
// Try all the ports for each resolved address
for (int port : PORTS_TO_TRY) { for (int port : PORTS_TO_TRY) {
DatagramPacket dp = new DatagramPacket(payload, payload.length); DatagramPacket dp = new DatagramPacket(payload, payload.length);
dp.setAddress(addr); dp.setAddress(resolvedAddress);
dp.setPort(port); dp.setPort(port);
sock.send(dp); sock.send(dp);
sentWolPacket = true;
} }
} }
} catch (IOException e) {
// We may have addresses that don't resolve on this subnet,
// but don't throw and exit the whole function if that happens.
// We'll throw it at the end if we didn't send a single packet.
e.printStackTrace();
lastException = e;
}
}
} finally {
sock.close();
}
sock.close(); // Propagate the DNS resolution exception if we didn't
// manage to get a single packet out to the host.
if (!sentWolPacket && lastException != null) {
throw lastException;
}
} }
private static byte[] macStringToBytes(String macAddress) { private static byte[] macStringToBytes(String macAddress) {