package net.jxta.impl.endpoint.netty;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import net.jxta.endpoint.EndpointAddress;
import net.jxta.impl.endpoint.IPUtils;
/**
* Socket address translator for traditional java InetSocketAddress instances, both IPv6 and IPv4.
*
* @author iain.mcginniss@onedrum.com
*/
public class InetSocketAddressTranslator implements AddressTranslator {
private String protocol;
public InetSocketAddressTranslator(String protocol) {
this.protocol = protocol;
}
public EndpointAddress toEndpointAddress(SocketAddress addr) {
InetSocketAddress socketAddr = (InetSocketAddress)addr;
String hostAddr;
if(socketAddr.isUnresolved()) {
hostAddr = socketAddr.getHostName();
} else {
hostAddr = IPUtils.getHostAddress(socketAddr.getAddress());
}
return new EndpointAddress(protocol, hostAddr + ":" + socketAddr.getPort(), null, null);
}
public EndpointAddress toEndpointAddress(SocketAddress clientAddr, SocketAddress serverAddr) {
InetSocketAddress serverInetAddr = (InetSocketAddress)serverAddr;
InetSocketAddress clientInetAddr = (InetSocketAddress)clientAddr;
return toEndpointAddress(new InetSocketAddress(clientInetAddr.getAddress(), serverInetAddr.getPort()));
}
public SocketAddress toSocketAddress(EndpointAddress addr) {
String protoAddr = addr.getProtocolAddress();
if(protoAddr.indexOf('[') != -1 || protoAddr.indexOf(']') != -1) {
return parseIPv6(protoAddr);
} else {
return parseIPv4(protoAddr);
}
}
private InetSocketAddress parseIPv6(String protoAddr) {
int indexOfCloseBracket = protoAddr.indexOf(']');
if(protoAddr.charAt(0) != '[' || indexOfCloseBracket == -1) {
throw new IllegalArgumentException("Address is not a valid IPv6 address <" + protoAddr + ">");
}
String hostPart = protoAddr.substring(1, indexOfCloseBracket);
if(indexOfCloseBracket == protoAddr.length()-1 || indexOfCloseBracket == protoAddr.length()-2) {
throw new IllegalArgumentException("No port specified in IPv6 address <" + protoAddr + ">");
}
if(protoAddr.charAt(indexOfCloseBracket+1) != ':') {
throw new IllegalArgumentException("No port specified in IPv6 address <" + protoAddr + ">");
}
String portPart = protoAddr.substring(indexOfCloseBracket+2);
int port = parsePort(portPart, protoAddr);
return new InetSocketAddress(hostPart, port);
}
private InetSocketAddress parseIPv4(String protoAddr) {
int indexOfColon = protoAddr.indexOf(":");
if(indexOfColon == -1 || indexOfColon == protoAddr.length()-1) {
throw new IllegalArgumentException("No port specified in address <" + protoAddr + ">");
}
if(indexOfColon == 0) {
throw new IllegalArgumentException("No host specified in address <" + protoAddr + ">");
}
String hostName = protoAddr.substring(0, indexOfColon);
String portStr = protoAddr.substring(indexOfColon+1);
int port = parsePort(portStr, protoAddr);
return new InetSocketAddress(hostName, port);
}
private int parsePort(String portStr, String fullAddr) {
int port;
try {
port = Integer.parseInt(portStr);
} catch(NumberFormatException e) {
throw new IllegalArgumentException("Port specified is not a valid number <" + fullAddr + ">");
}
if(port < 0 || port > 65535) {
throw new IllegalArgumentException("Port specified is not in the legal range <" + fullAddr + ">");
}
return port;
}
public List<EndpointAddress> translateToExternalAddresses(SocketAddress bindpoint) {
if(bindpoint == null) {
return Collections.emptyList();
}
InetSocketAddress bpInet = (InetSocketAddress) bindpoint;
List<EndpointAddress> externalAddresses = new LinkedList<EndpointAddress>();
if(IPUtils.ANYADDRESS.equals(bpInet.getAddress())) {
for(InetAddress localAddress : IPUtils.getAllLocalAddresses()) {
// ignore loopback and link local addresses - they are useless for routing
// in most scenarios.
if (localAddress.isLoopbackAddress() || localAddress.isLinkLocalAddress()) {
continue;
}
SocketAddress externalAddress = new InetSocketAddress(localAddress, bpInet.getPort());
externalAddresses.add(toEndpointAddress(externalAddress));
}
// we sort them so that later equals() will be deterministic.
// the result of IPUtils.getAllLocalAddresses() is not known to
// be sorted.
sortAddresses(externalAddresses);
} else {
externalAddresses.add(toEndpointAddress(bindpoint));
}
return externalAddresses;
}
private void sortAddresses(List<EndpointAddress> externalAddresses) {
Collections.sort(externalAddresses, new Comparator<EndpointAddress>() {
public int compare(EndpointAddress one, EndpointAddress two) {
return one.toString().compareTo(two.toString());
}
public boolean equals(Object that) {
return (this == that);
}
});
}
public String getProtocolName() {
return protocol;
}
}