@ -21,6 +21,7 @@ import org.hyperledger.besu.util.NetworkUtility;
import java.net.InetAddress ;
import java.net.URI ;
import java.net.UnknownHostException ;
import java.util.Objects ;
import java.util.Optional ;
import java.util.OptionalInt ;
@ -40,13 +41,15 @@ public class EnodeURL {
private static final Pattern NODE_ID_PATTERN = Pattern . compile ( "^[0-9a-fA-F]{128}$" ) ;
private final Bytes nodeId ;
private final InetAddress ip ;
private InetAddress ip ;
private final Optional < String > maybeHostname ;
private final Optional < Integer > listeningPort ;
private final Optional < Integer > discoveryPort ;
private EnodeURL (
final Bytes nodeId ,
final InetAddress address ,
final Optional < String > maybeHostname ,
final Optional < Integer > listeningPort ,
final Optional < Integer > discoveryPort ) {
checkArgument (
@ -56,6 +59,7 @@ public class EnodeURL {
this . nodeId = nodeId ;
this . ip = address ;
this . maybeHostname = maybeHostname ;
this . listeningPort = listeningPort ;
this . discoveryPort = discoveryPort ;
}
@ -65,9 +69,14 @@ public class EnodeURL {
}
public static EnodeURL fromString ( final String value ) {
return fromString ( value , EnodeDnsConfiguration . dnsDisabled ( ) ) ;
}
public static EnodeURL fromString (
final String value , final EnodeDnsConfiguration enodeDnsConfiguration ) {
try {
checkStringArgumentNotEmpty ( value , "Invalid empty value." ) ;
return fromURI ( URI . create ( value ) ) ;
return fromURI ( URI . create ( value ) , enodeDnsConfiguration ) ;
} catch ( IllegalArgumentException e ) {
String message =
"Invalid enode URL syntax. Enode URL should have the following format 'enode://<node_id>@<ip>:<listening_port>[?discport=<discovery_port>]'." ;
@ -79,6 +88,10 @@ public class EnodeURL {
}
public static EnodeURL fromURI ( final URI uri ) {
return fromURI ( uri , EnodeDnsConfiguration . dnsDisabled ( ) ) ;
}
public static EnodeURL fromURI ( final URI uri , final EnodeDnsConfiguration enodeDnsConfiguration ) {
checkArgument ( uri ! = null , "URI cannot be null" ) ;
checkStringArgumentNotEmpty ( uri . getScheme ( ) , "Missing 'enode' scheme." ) ;
checkStringArgumentNotEmpty ( uri . getHost ( ) , "Missing or invalid ip address." ) ;
@ -108,7 +121,7 @@ public class EnodeURL {
}
return builder ( )
. ipAddress ( host )
. ipAddress ( host , enodeDnsConfiguration )
. nodeId ( id )
. listeningPort ( tcpPort )
. discoveryPort ( discoveryPort )
@ -124,9 +137,9 @@ public class EnodeURL {
return false ;
}
return Objects . equals ( enodeA . nodeId , enodeB . nodeId )
& & Objects . equals ( enodeA . ip , enodeB . ip )
& & Objects . equals ( enodeA . listeningPort , enodeB . listeningPort ) ;
return Objects . equals ( enodeA . getNodeId ( ) , enodeB . getNodeId ( ) )
& & Objects . equals ( enodeA . getIp ( ) , enodeB . getIp ( ) )
& & Objects . equals ( enodeA . getListeningPort ( ) , enodeB . getListeningPort ( ) ) ;
}
public static Bytes parseNodeId ( final String nodeId ) {
@ -141,11 +154,12 @@ public class EnodeURL {
}
public URI toURI ( ) {
final String uri =
String . format (
"enode://%s@%s:%d" ,
nodeId . toUnprefixedHexString ( ) ,
InetAddresses . toUriString ( ip ) ,
maybeHostname . orElse ( InetAddresses . toUriString ( getIp ( ) ) ) ,
getListeningPortOrZero ( ) ) ;
final OptionalInt discPort = getDiscPortQueryParam ( ) ;
if ( discPort . isPresent ( ) ) {
@ -160,7 +174,7 @@ public class EnodeURL {
String . format (
"enode://%s@%s:%d" ,
nodeId . toUnprefixedHexString ( ) ,
InetAddresses . toUriString ( ip ) ,
maybeHostname . orElse ( InetAddresses . toUriString ( getIp ( ) ) ) ,
getListeningPortOrZero ( ) ) ;
return URI . create ( uri ) ;
@ -181,7 +195,11 @@ public class EnodeURL {
}
public static URI asURI ( final String url ) {
return fromString ( url ) . toURI ( ) ;
return asURI ( url , EnodeDnsConfiguration . dnsDisabled ( ) ) ;
}
public static URI asURI ( final String url , final EnodeDnsConfiguration enodeDnsConfiguration ) {
return fromString ( url , enodeDnsConfiguration ) . toURI ( ) ;
}
public Bytes getNodeId ( ) {
@ -189,10 +207,32 @@ public class EnodeURL {
}
public String getIpAsString ( ) {
return ip . getHostAddress ( ) ;
return getIp ( ) . getHostAddress ( ) ;
}
/ * *
* Get IP of the EnodeURL
*
* < p > If "dns" and "dns-update" are enabled - & gt ; DNS lookup every time to have the IP up to date
* and not to rely on an invalid cache
*
* < p > If the "dns" is enabled but "dns-update" is disabled - & gt ; IP is retrieved only one time and
* the hostname is no longer stored ( maybeHostname is empty ) .
*
* @return ip
* /
public InetAddress getIp ( ) {
this . ip =
maybeHostname
. map (
hostname - > {
try {
return InetAddress . getByName ( hostname ) ;
} catch ( UnknownHostException e ) {
return ip ;
}
} )
. orElse ( ip ) ;
return ip ;
}
@ -229,15 +269,15 @@ public class EnodeURL {
return false ;
}
EnodeURL enodeURL = ( EnodeURL ) o ;
return Objects . equals ( nodeId , enodeURL . nodeId )
& & Objects . equals ( ip , enodeURL . ip )
& & Objects . equals ( listeningPort , enodeURL . listeningPort )
& & Objects . equals ( discoveryPort , enodeURL . discoveryPort ) ;
return Objects . equals ( getNodeId ( ) , enodeURL . getNodeId ( ) )
& & Objects . equals ( getIp ( ) , enodeURL . getIp ( ) )
& & Objects . equals ( getListeningPort ( ) , enodeURL . getListeningPort ( ) )
& & Objects . equals ( getDiscoveryPort ( ) , enodeURL . getDiscoveryPort ( ) ) ;
}
@Override
public int hashCode ( ) {
return Objects . hash ( nodeId , ip , listeningPort , discoveryPort ) ;
return Objects . hash ( getNodeId ( ) , getIp ( ) , getListeningPort ( ) , getDiscoveryPort ( ) ) ;
}
@Override
@ -250,13 +290,14 @@ public class EnodeURL {
private Bytes nodeId ;
private Optional < Integer > listeningPort ;
private Optional < Integer > discoveryPort ;
private Optional < String > maybeHostname = Optional . empty ( ) ;
private InetAddress ip ;
private Builder ( ) { }
public EnodeURL build ( ) {
validate ( ) ;
return new EnodeURL ( nodeId , ip , listeningPort , discoveryPort ) ;
return new EnodeURL ( nodeId , ip , maybeHostname , listeningPort , discoveryPort ) ;
}
private void validate ( ) {
@ -294,10 +335,27 @@ public class EnodeURL {
}
public Builder ipAddress ( final String ip ) {
return ipAddress ( ip , EnodeDnsConfiguration . dnsDisabled ( ) ) ;
}
public Builder ipAddress ( final String ip , final EnodeDnsConfiguration enodeDnsConfiguration ) {
if ( InetAddresses . isUriInetAddress ( ip ) ) {
this . ip = InetAddresses . forUriString ( ip ) ;
} else if ( InetAddresses . isInetAddress ( ip ) ) {
this . ip = InetAddresses . forString ( ip ) ;
} else if ( enodeDnsConfiguration . dnsEnabled ( ) ) {
try {
if ( enodeDnsConfiguration . updateEnabled ( ) ) {
this . maybeHostname = Optional . of ( ip ) ;
}
this . ip = InetAddress . getByName ( ip ) ;
} catch ( UnknownHostException e ) {
if ( ! enodeDnsConfiguration . updateEnabled ( ) ) {
throw new IllegalArgumentException ( "Invalid ip address or hostname." ) ;
} else {
this . ip = InetAddresses . forString ( "127.0.0.1" ) ;
}
}
} else {
throw new IllegalArgumentException ( "Invalid ip address." ) ;
}