diff --git a/pom.xml b/pom.xml
index 39bb993..4368961 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.bwssystems.HABridge
ha-bridge
- 5.2.2
+ 5.2.1a
jar
HA Bridge
diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
index eef0d7e..5e9ce8d 100644
--- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
+++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
@@ -215,8 +215,10 @@ public class BridgeSettings extends BackupHandler {
// Lifx is either configured or not, so it does not need an update.
if(serverPortOverride != null)
theBridgeSettings.setServerPort(serverPortOverride);
- if(serverIpOverride != null)
+ if(serverIpOverride != null) {
theBridgeSettings.setWebaddress(serverIpOverride);
+ theBridgeSettings.setUpnpConfigAddress(serverIpOverride);
+ }
if(upnpStrictOverride != null)
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride));
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
index 980de3b..26e4925 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
@@ -22,7 +22,7 @@ public class UpnpListener {
private Logger log = LoggerFactory.getLogger(UpnpListener.class);
private MulticastSocket upnpMulticastSocket;
private int httpServerPort;
- private String responseAddress;
+ private String upnpConfigIP;
private boolean strict;
private boolean traceupnp;
private boolean useUpnpIface;
@@ -73,17 +73,20 @@ public class UpnpListener {
super();
upnpMulticastSocket = null;
httpServerPort = Integer.valueOf(theSettings.getServerPort());
- responseAddress = theSettings.getUpnpConfigAddress();
+ upnpConfigIP = theSettings.getUpnpConfigAddress();
strict = theSettings.isUpnpStrict();
traceupnp = theSettings.isTraceupnp();
useUpnpIface = theSettings.isUseupnpiface();
theUpnpSendDelay = theSettings.getUpnpsenddelay();
bridgeControl = theControl;
- aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION, theSettings.getHubmac());
+ aHueConfig = HuePublicConfig.createConfig("temp", upnpConfigIP, HueConstants.HUB_VERSION, theSettings.getHubmac());
bridgeId = aHueConfig.getBridgeid();
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
try {
- upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
+ if(useUpnpIface)
+ upnpMulticastSocket = new MulticastSocket(new InetSocketAddress(upnpConfigIP, Configuration.UPNP_DISCOVERY_PORT));
+ else
+ upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
} catch(IOException e){
log.error("Upnp Discovery Port is in use, or restricted by admin (try running with sudo or admin privs): " + Configuration.UPNP_DISCOVERY_PORT + " with message: " + e.getMessage());
throw(e);
@@ -118,7 +121,7 @@ public class UpnpListener {
log.info("Traceupnp: Interface: " + name + " valid usable IP address: " + addr);
IPsPerNic++;
}
- else if(addr.getHostAddress().equals(responseAddress)) {
+ else if(addr.getHostAddress().equals(upnpConfigIP)) {
if(traceupnp)
log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + addr);
IPsPerNic++;
@@ -157,7 +160,7 @@ public class UpnpListener {
upnpMulticastSocket.receive(packet);
if (isSSDPDiscovery(packet)) {
try {
- sendUpnpResponse(packet.getAddress(), packet.getPort());
+ sendUpnpResponse(packet);
} catch (IOException e) {
log.warn("UpnpListener encountered an error sending upnp response packet. IP: " + packet.getAddress().getHostAddress() + " with message: " + e.getMessage());
log.debug("UpnpListener send upnp exception: ", e);
@@ -230,16 +233,21 @@ public class UpnpListener {
return false;
}
- protected void sendUpnpResponse(InetAddress requester, int sourcePort) throws IOException {
+ protected void sendUpnpResponse(DatagramPacket aPacket) throws IOException {
+ SocketAddress requesterAddress = aPacket.getSocketAddress();
+ InetAddress requester = aPacket.getAddress();
+ int sourcePort = aPacket.getPort();
String discoveryResponse = null;
+ // refactored suggestion by https://github.com/pvint
+ String httpLocationAddress = getOutboundAddress(requesterAddress).getHostAddress();
try {
Thread.sleep(theUpnpSendDelay);
} catch (InterruptedException e) {
// noop
}
- discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
+ discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID);
if(traceupnp) {
- log.info("Traceupnp: send upnp discovery template 1 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
+ log.info("Traceupnp: send upnp discovery template 1 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
}
else
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
@@ -250,9 +258,9 @@ public class UpnpListener {
} catch (InterruptedException e) {
// noop
}
- discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
+ discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
if(traceupnp) {
- log.info("Traceupnp: send upnp discovery template 2 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
+ log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
}
else
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
@@ -263,9 +271,9 @@ public class UpnpListener {
} catch (InterruptedException e) {
// noop
}
- discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
+ discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID);
if(traceupnp) {
- log.info("Traceupnp: send upnp discovery template 3 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
+ log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
}
else
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
@@ -282,7 +290,7 @@ public class UpnpListener {
protected void sendUpnpNotify(InetAddress aSocketAddress) {
String notifyData = null;
- notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
+ notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, upnpConfigIP, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
log.debug("sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT);
try {
@@ -291,6 +299,20 @@ public class UpnpListener {
log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage());
log.debug("UpnpListener send upnp notify exception: ", e1);
}
+ }
+ // added by https://github.com/pvint
+ // Ruthlessly stolen from https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface
+ // Try to get a source IP that makes sense for the requestor to contact for use in the LOCATION header in replies
+ private InetAddress getOutboundAddress(SocketAddress remoteAddress) throws SocketException {
+ DatagramSocket sock = new DatagramSocket();
+ // connect is needed to bind the socket and retrieve the local address
+ // later (it would return 0.0.0.0 otherwise)
+ sock.connect(remoteAddress);
+ final InetAddress localAddress = sock.getLocalAddress();
+ sock.disconnect();
+ sock.close();
+ sock = null;
+ return localAddress;
}
}
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
index fa98b07..f6e644f 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
@@ -10,6 +10,11 @@ import com.bwssystems.HABridge.api.hue.HuePublicConfig;
import static spark.Spark.get;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+
/**
*
*/
@@ -75,12 +80,13 @@ public class UpnpSettingsResource {
String portNumber = Integer.toString(request.port());
String filledTemplate = null;
- String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress(), HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
- filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress(), bridgeIdMac, bridgeIdMac);
+ String httpLocationAddr = getOutboundAddress(request.ip(), request.port()).getHostAddress();
+ String bridgeIdMac = HuePublicConfig.createConfig("temp", httpLocationAddr, HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
+ filledTemplate = String.format(hueTemplate, httpLocationAddr, portNumber, httpLocationAddr, bridgeIdMac, bridgeIdMac);
if(theSettings.isTraceupnp())
- log.info("Traceupnp: request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
+ log.info("Traceupnp: request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + httpLocationAddr + ":" + portNumber);
else
- log.debug("request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
+ log.debug("request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + httpLocationAddr + ":" + portNumber);
// response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
// response.header("Pragma", "no-cache");
// response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT");
@@ -109,4 +115,18 @@ public class UpnpSettingsResource {
return "";
} );
}
+ // added by https://github.com/pvint
+ // Ruthlessly stolen from https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface
+ // Try to get a source IP that makes sense for the requester to contact for use in the LOCATION header in replies
+ private InetAddress getOutboundAddress(String remoteAddress, int remotePort) throws SocketException {
+ DatagramSocket sock = new DatagramSocket();
+ // connect is needed to bind the socket and retrieve the local address
+ // later (it would return 0.0.0.0 otherwise)
+ sock.connect(InetSocketAddress.createUnresolved(remoteAddress, remotePort));
+ final InetAddress localAddress = sock.getLocalAddress();
+ sock.disconnect();
+ sock.close();
+ sock = null;
+ return localAddress;
+ }
}