@@ -57,6 +57,9 @@ public class NetUtils {
5757 private static final Map <String , String > hostNameCache = new LRUCache <>(1000 );
5858 private static volatile InetAddress LOCAL_ADDRESS = null ;
5959
60+ private static final String SPLIT_IPV4_CHARECTER = "\\ ." ;
61+ private static final String SPLIT_IPV6_CHARECTER = ":" ;
62+
6063 public static int getRandomPort () {
6164 return RND_PORT_START + ThreadLocalRandom .current ().nextInt (RND_PORT_RANGE );
6265 }
@@ -340,13 +343,13 @@ public static String toURL(String protocol, String host, int port, String path)
340343 return sb .toString ();
341344 }
342345
343- public static void joinMulticastGroup (MulticastSocket multicastSocket , InetAddress multicastAddress ) throws IOException {
346+ public static void joinMulticastGroup (MulticastSocket multicastSocket , InetAddress multicastAddress ) throws IOException {
344347 setInterface (multicastSocket , multicastAddress instanceof Inet6Address );
345348 multicastSocket .setLoopbackMode (false );
346349 multicastSocket .joinGroup (multicastAddress );
347350 }
348351
349- public static void setInterface (MulticastSocket multicastSocket , boolean preferIpv6 ) throws IOException {
352+ public static void setInterface (MulticastSocket multicastSocket , boolean preferIpv6 ) throws IOException {
350353 boolean interfaceSet = false ;
351354 Enumeration interfaces = NetworkInterface .getNetworkInterfaces ();
352355 while (interfaces .hasMoreElements ()) {
@@ -370,4 +373,134 @@ public static void setInterface (MulticastSocket multicastSocket, boolean prefer
370373 }
371374 }
372375
376+ public static boolean matchIpExpression (String pattern , String host , int port ) throws UnknownHostException {
377+
378+ // if the pattern is subnet format, it will not be allowed to config port param in pattern.
379+ if (pattern .contains ("/" )) {
380+ CIDRUtils utils = new CIDRUtils (pattern );
381+ return utils .isInRange (host );
382+ }
383+
384+
385+ return matchIpRange (pattern , host , port );
386+ }
387+
388+ /**
389+ * @param pattern
390+ * @param host
391+ * @param port
392+ * @return
393+ * @throws UnknownHostException
394+ */
395+ public static boolean matchIpRange (String pattern , String host , int port ) throws UnknownHostException {
396+ if (pattern == null || host == null ) {
397+ throw new IllegalArgumentException ("Illegal Argument pattern or hostName. Pattern:" + pattern + ", Host:" + host );
398+ }
399+ pattern = pattern .trim ();
400+ if (pattern .equals ("*.*.*.*" ) || pattern .equals ("*" )) {
401+ return true ;
402+ }
403+
404+ InetAddress inetAddress = InetAddress .getByName (host );
405+ boolean isIpv4 = isValidV4Address (inetAddress ) ? true : false ;
406+ String [] hostAndPort = getPatternHostAndPort (pattern , isIpv4 );
407+ if (hostAndPort [1 ] != null && !hostAndPort [1 ].equals (String .valueOf (port ))) {
408+ return false ;
409+ }
410+ pattern = hostAndPort [0 ];
411+
412+ String splitCharacter = SPLIT_IPV4_CHARECTER ;
413+ if (!isIpv4 ) {
414+ splitCharacter = SPLIT_IPV6_CHARECTER ;
415+ }
416+ String [] mask = pattern .split (splitCharacter );
417+ //check format of pattern
418+ checkHostPattern (pattern , mask , isIpv4 );
419+
420+ host = inetAddress .getHostAddress ();
421+
422+ String [] ip_address = host .split (splitCharacter );
423+ if (pattern .equals (host )) {
424+ return true ;
425+ }
426+ // short name condition
427+ if (!ipPatternContainExpression (pattern )) {
428+ InetAddress patternAddress = InetAddress .getByName (pattern );
429+ if (patternAddress .getHostAddress ().equals (host )) {
430+ return true ;
431+ } else {
432+ return false ;
433+ }
434+ }
435+ for (int i = 0 ; i < mask .length ; i ++) {
436+ if (mask [i ].equals ("*" ) || mask [i ].equals (ip_address [i ])) {
437+ continue ;
438+ } else if (mask [i ].contains ("-" )) {
439+ String [] rangeNumStrs = mask [i ].split ("-" );
440+ if (rangeNumStrs .length != 2 ) {
441+ throw new IllegalArgumentException ("There is wrong format of ip Address: " + mask [i ]);
442+ }
443+ Integer min = getNumOfIpSegment (rangeNumStrs [0 ], isIpv4 );
444+ Integer max = getNumOfIpSegment (rangeNumStrs [1 ], isIpv4 );
445+ Integer ip = getNumOfIpSegment (ip_address [i ], isIpv4 );
446+ if (ip < min || ip > max ) {
447+ return false ;
448+ }
449+ } else if ("0" .equals (ip_address [i ]) && ("0" .equals (mask [i ]) || "00" .equals (mask [i ]) || "000" .equals (mask [i ]) || "0000" .equals (mask [i ]))) {
450+ continue ;
451+ } else if (!mask [i ].equals (ip_address [i ])) {
452+ return false ;
453+ }
454+ }
455+ return true ;
456+ }
457+
458+ private static boolean ipPatternContainExpression (String pattern ) {
459+ return pattern .contains ("*" ) || pattern .contains ("-" );
460+ }
461+
462+ private static void checkHostPattern (String pattern , String [] mask , boolean isIpv4 ) {
463+ if (!isIpv4 ) {
464+ if (mask .length != 8 && ipPatternContainExpression (pattern )) {
465+ throw new IllegalArgumentException ("If you config ip expression that contains '*' or '-', please fill qulified ip pattern like 234e:0:4567:0:0:0:3d:*. " );
466+ }
467+ if (mask .length != 8 && !pattern .contains ("::" )) {
468+ throw new IllegalArgumentException ("The host is ipv6, but the pattern is not ipv6 pattern : " + pattern );
469+ }
470+ } else {
471+ if (mask .length != 4 ) {
472+ throw new IllegalArgumentException ("The host is ipv4, but the pattern is not ipv4 pattern : " + pattern );
473+ }
474+ }
475+ }
476+
477+ private static String [] getPatternHostAndPort (String pattern , boolean isIpv4 ) {
478+ String [] result = new String [2 ];
479+ if (pattern .startsWith ("[" ) && pattern .contains ("]:" )) {
480+ int end = pattern .indexOf ("]:" );
481+ result [0 ] = pattern .substring (1 , end );
482+ result [1 ] = pattern .substring (end + 2 );
483+ return result ;
484+ } else if (pattern .startsWith ("[" ) && pattern .endsWith ("]" )) {
485+ result [0 ] = pattern .substring (1 , pattern .length () - 1 );
486+ result [1 ] = null ;
487+ return result ;
488+ } else if (isIpv4 && pattern .contains (":" )) {
489+ int end = pattern .indexOf (":" );
490+ result [0 ] = pattern .substring (0 , end );
491+ result [1 ] = pattern .substring (end + 1 );
492+ return result ;
493+ } else {
494+ result [0 ] = pattern ;
495+ return result ;
496+ }
497+ }
498+
499+ private static Integer getNumOfIpSegment (String ipSegment , boolean isIpv4 ) {
500+ if (isIpv4 ) {
501+ return Integer .parseInt (ipSegment );
502+ }
503+ return Integer .parseInt (ipSegment , 16 );
504+ }
505+
373506}
0 commit comments