Refactored address parsing code into superclass. Don't use DNS.

This commit is contained in:
akwizgran
2014-04-04 13:45:05 +01:00
parent fe82591fdf
commit 75f13f53a0
3 changed files with 40 additions and 65 deletions

View File

@@ -8,7 +8,6 @@ import java.net.InetSocketAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.SocketException; import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@@ -18,7 +17,6 @@ import java.util.logging.Logger;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.util.StringUtils;
/** A TCP plugin that supports exchanging invitations over a LAN. */ /** A TCP plugin that supports exchanging invitations over a LAN. */
class LanTcpPlugin extends TcpPlugin { class LanTcpPlugin extends TcpPlugin {
@@ -42,23 +40,9 @@ class LanTcpPlugin extends TcpPlugin {
protected List<SocketAddress> getLocalSocketAddresses() { protected List<SocketAddress> getLocalSocketAddresses() {
// Use the same address and port as last time if available // Use the same address and port as last time if available
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
String addressString = p.get("address"); InetSocketAddress old = parseSocketAddress(p.get("address"),
String portString = p.get("port"); p.get("port"));
InetAddress oldAddress = null; // Get a list of the device's network interfaces
int oldPort = 0;
if(!StringUtils.isNullOrEmpty(addressString) &&
!StringUtils.isNullOrEmpty(portString)) {
try {
oldAddress = InetAddress.getByName(addressString);
oldPort = Integer.parseInt(portString);
} catch(NumberFormatException e) {
if(LOG.isLoggable(WARNING))
LOG.warning("Invalid port: " + portString);
} catch(UnknownHostException e) {
if(LOG.isLoggable(WARNING))
LOG.warning("Invalid address: " + addressString);
}
}
List<NetworkInterface> ifaces; List<NetworkInterface> ifaces;
try { try {
ifaces = Collections.list(NetworkInterface.getNetworkInterfaces()); ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
@@ -66,8 +50,8 @@ class LanTcpPlugin extends TcpPlugin {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return Collections.emptyList(); return Collections.emptyList();
} }
List<SocketAddress> addresses = new LinkedList<SocketAddress>(); List<SocketAddress> addrs = new LinkedList<SocketAddress>();
// Accept interfaces with link-local or site-local addresses // Accept interfaces with local IPv4 addresses
for(NetworkInterface iface : ifaces) { for(NetworkInterface iface : ifaces) {
for(InetAddress a : Collections.list(iface.getInetAddresses())) { for(InetAddress a : Collections.list(iface.getInetAddresses())) {
boolean ipv4 = a instanceof Inet4Address; boolean ipv4 = a instanceof Inet4Address;
@@ -75,12 +59,13 @@ class LanTcpPlugin extends TcpPlugin {
boolean link = a.isLinkLocalAddress(); boolean link = a.isLinkLocalAddress();
boolean site = a.isSiteLocalAddress(); boolean site = a.isSiteLocalAddress();
if(ipv4 && !loop && (link || site)) { if(ipv4 && !loop && (link || site)) {
if(a.equals(oldAddress)) // If this is the old address, try to use the same port
addresses.add(0, new InetSocketAddress(a, oldPort)); if(old != null && old.getAddress().equals(a))
addresses.add(new InetSocketAddress(a, 0)); addrs.add(0, new InetSocketAddress(a, old.getPort()));
addrs.add(new InetSocketAddress(a, 0));
} }
} }
} }
return addresses; return addrs;
} }
} }

View File

@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.briarproject.api.ContactId; import org.briarproject.api.ContactId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
@@ -26,6 +27,8 @@ import org.briarproject.util.StringUtils;
abstract class TcpPlugin implements DuplexPlugin { abstract class TcpPlugin implements DuplexPlugin {
private static final Pattern DOTTED_QUAD =
Pattern.compile("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$");
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TcpPlugin.class.getName()); Logger.getLogger(TcpPlugin.class.getName());
@@ -81,7 +84,6 @@ abstract class TcpPlugin implements DuplexPlugin {
break; break;
} catch(IOException e) { } catch(IOException e) {
if(LOG.isLoggable(INFO)) LOG.info("Failed to bind " + addr); if(LOG.isLoggable(INFO)) LOG.info("Failed to bind " + addr);
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
tryToClose(ss); tryToClose(ss);
continue; continue;
} }
@@ -196,19 +198,23 @@ abstract class TcpPlugin implements DuplexPlugin {
private SocketAddress getRemoteSocketAddress(ContactId c) { private SocketAddress getRemoteSocketAddress(ContactId c) {
TransportProperties p = callback.getRemoteProperties().get(c); TransportProperties p = callback.getRemoteProperties().get(c);
if(p == null) return null; if(p == null) return null;
String addrString = p.get("address"); return parseSocketAddress(p.get("address"), p.get("port"));
if(StringUtils.isNullOrEmpty(addrString)) return null; }
String portString = p.get("port");
if(StringUtils.isNullOrEmpty(portString)) return null; protected InetSocketAddress parseSocketAddress(String addr, String port) {
if(StringUtils.isNullOrEmpty(addr)) return null;
if(StringUtils.isNullOrEmpty(port)) return null;
// Ensure getByName() won't perform a DNS lookup
if(!DOTTED_QUAD.matcher(addr).matches()) return null;
try { try {
InetAddress addr = InetAddress.getByName(addrString); InetAddress a = InetAddress.getByName(addr);
int port = Integer.parseInt(portString); int p = Integer.parseInt(port);
return new InetSocketAddress(addr, port); return new InetSocketAddress(a, p);
} catch(NumberFormatException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null;
} catch(UnknownHostException e) { } catch(UnknownHostException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if(LOG.isLoggable(WARNING)) LOG.warning("Invalid address: " + addr);
return null;
} catch(NumberFormatException e) {
if(LOG.isLoggable(WARNING)) LOG.warning("Invalid port: " + port);
return null; return null;
} }
} }

View File

@@ -8,7 +8,6 @@ import java.net.InetSocketAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.SocketException; import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@@ -18,7 +17,6 @@ import java.util.logging.Logger;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.util.StringUtils;
class WanTcpPlugin extends TcpPlugin { class WanTcpPlugin extends TcpPlugin {
@@ -47,23 +45,8 @@ class WanTcpPlugin extends TcpPlugin {
protected List<SocketAddress> getLocalSocketAddresses() { protected List<SocketAddress> getLocalSocketAddresses() {
// Use the same address and port as last time if available // Use the same address and port as last time if available
TransportProperties p = callback.getLocalProperties(); TransportProperties p = callback.getLocalProperties();
String addressString = p.get("address"); InetSocketAddress old = parseSocketAddress(p.get("address"),
String portString = p.get("port"); p.get("port"));
InetAddress oldAddress = null;
int oldPort = 0;
if(!StringUtils.isNullOrEmpty(addressString) &&
!StringUtils.isNullOrEmpty(portString)) {
try {
oldAddress = InetAddress.getByName(addressString);
oldPort = Integer.parseInt(portString);
} catch(NumberFormatException e) {
if(LOG.isLoggable(WARNING))
LOG.warning("Invalid port: " + portString);
} catch(UnknownHostException e) {
if(LOG.isLoggable(WARNING))
LOG.warning("Invalid address: " + addressString);
}
}
// Get a list of the device's network interfaces // Get a list of the device's network interfaces
List<NetworkInterface> ifaces; List<NetworkInterface> ifaces;
try { try {
@@ -72,8 +55,8 @@ class WanTcpPlugin extends TcpPlugin {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return Collections.emptyList(); return Collections.emptyList();
} }
List<SocketAddress> addresses = new LinkedList<SocketAddress>(); List<SocketAddress> addrs = new LinkedList<SocketAddress>();
// Accept interfaces without link-local or site-local addresses // Accept interfaces without global IPv4 addresses
for(NetworkInterface iface : ifaces) { for(NetworkInterface iface : ifaces) {
for(InetAddress a : Collections.list(iface.getInetAddresses())) { for(InetAddress a : Collections.list(iface.getInetAddresses())) {
boolean ipv4 = a instanceof Inet4Address; boolean ipv4 = a instanceof Inet4Address;
@@ -81,20 +64,21 @@ class WanTcpPlugin extends TcpPlugin {
boolean link = a.isLinkLocalAddress(); boolean link = a.isLinkLocalAddress();
boolean site = a.isSiteLocalAddress(); boolean site = a.isSiteLocalAddress();
if(ipv4 && !loop && !link && !site) { if(ipv4 && !loop && !link && !site) {
if(a.equals(oldAddress)) // If this is the old address, try to use the same port
addresses.add(0, new InetSocketAddress(a, oldPort)); if(old != null && old.getAddress().equals(a))
addresses.add(new InetSocketAddress(a, 0)); addrs.add(0, new InetSocketAddress(a, old.getPort()));
addrs.add(new InetSocketAddress(a, 0));
} }
} }
} }
// Accept interfaces with local addresses that can be port-mapped // Accept interfaces with local addresses that can be port-mapped
if(oldPort == 0) oldPort = chooseEphemeralPort(); int port = old == null ? chooseEphemeralPort() : old.getPort();
mappingResult = portMapper.map(oldPort); mappingResult = portMapper.map(port);
if(mappingResult != null && mappingResult.isUsable()) { if(mappingResult != null && mappingResult.isUsable()) {
InetSocketAddress a = mappingResult.getInternal(); InetSocketAddress a = mappingResult.getInternal();
if(a.getAddress() instanceof Inet4Address) addresses.add(a); if(a.getAddress() instanceof Inet4Address) addrs.add(a);
} }
return addresses; return addrs;
} }
private int chooseEphemeralPort() { private int chooseEphemeralPort() {