1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.util;
17
18 import io.netty5.util.NetUtilInitializations.NetworkIfaceAndInetAddress;
19 import io.netty5.util.internal.PlatformDependent;
20 import io.netty5.util.internal.StringUtil;
21 import io.netty5.util.internal.SystemPropertyUtil;
22 import io.netty5.util.internal.logging.InternalLogger;
23 import io.netty5.util.internal.logging.InternalLoggerFactory;
24
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.FileReader;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.net.Inet4Address;
32 import java.net.Inet6Address;
33 import java.net.InetAddress;
34 import java.net.InetSocketAddress;
35 import java.net.NetworkInterface;
36 import java.net.ProtocolFamily;
37 import java.net.StandardProtocolFamily;
38 import java.net.UnknownHostException;
39 import java.security.AccessController;
40 import java.security.PrivilegedAction;
41 import java.util.Arrays;
42
43 import static io.netty5.util.AsciiString.indexOf;
44
45
46
47
48
49
50
51
52 public final class NetUtil {
53
54
55
56
57 public static final Inet4Address LOCALHOST4;
58
59
60
61
62 public static final Inet6Address LOCALHOST6;
63
64
65
66
67
68 public static final InetAddress LOCALHOST;
69
70
71
72
73 public static final NetworkInterface LOOPBACK_IF;
74
75
76
77
78
79 public static final int SOMAXCONN;
80
81
82
83
84 private static final int IPV6_WORD_COUNT = 8;
85
86
87
88
89 private static final int IPV6_MAX_CHAR_COUNT = 39;
90
91
92
93
94 private static final int IPV6_BYTE_COUNT = 16;
95
96
97
98
99 private static final int IPV6_MAX_CHAR_BETWEEN_SEPARATOR = 4;
100
101
102
103
104 private static final int IPV6_MIN_SEPARATORS = 2;
105
106
107
108
109 private static final int IPV6_MAX_SEPARATORS = 8;
110
111
112
113
114 private static final int IPV4_MAX_CHAR_BETWEEN_SEPARATOR = 3;
115
116
117
118
119 private static final int IPV4_SEPARATORS = 3;
120
121
122
123
124 private static final boolean IPV4_PREFERRED = SystemPropertyUtil.getBoolean("java.net.preferIPv4Stack", false);
125
126
127
128
129 private static final boolean IPV6_ADDRESSES_PREFERRED =
130 SystemPropertyUtil.getBoolean("java.net.preferIPv6Addresses", false);
131
132
133
134
135 private static final InternalLogger logger = InternalLoggerFactory.getInstance(NetUtil.class);
136
137 static {
138 logger.debug("-Djava.net.preferIPv4Stack: {}", IPV4_PREFERRED);
139 logger.debug("-Djava.net.preferIPv6Addresses: {}", IPV6_ADDRESSES_PREFERRED);
140
141
142 LOCALHOST4 = NetUtilInitializations.createLocalhost4();
143
144
145 LOCALHOST6 = NetUtilInitializations.createLocalhost6();
146
147 NetworkIfaceAndInetAddress loopback = NetUtilInitializations.determineLoopback(LOCALHOST4, LOCALHOST6);
148 LOOPBACK_IF = loopback.iface();
149 LOCALHOST = loopback.address();
150
151
152
153
154 SOMAXCONN = AccessController.doPrivileged(new SoMaxConnAction());
155 }
156
157 private static final class SoMaxConnAction implements PrivilegedAction<Integer> {
158 @Override
159 public Integer run() {
160
161
162
163
164 int somaxconn = PlatformDependent.isWindows() ? 200 : 128;
165 File file = new File("/proc/sys/net/core/somaxconn");
166 BufferedReader in = null;
167 try {
168
169
170
171 if (file.exists()) {
172 in = new BufferedReader(new FileReader(file));
173 somaxconn = Integer.parseInt(in.readLine());
174 if (logger.isDebugEnabled()) {
175 logger.debug("{}: {}", file, somaxconn);
176 }
177 } else {
178
179 Integer tmp = null;
180 if (SystemPropertyUtil.getBoolean("io.netty5.net.somaxconn.trySysctl", false)) {
181 tmp = sysctlGetInt("kern.ipc.somaxconn");
182 if (tmp == null) {
183 tmp = sysctlGetInt("kern.ipc.soacceptqueue");
184 if (tmp != null) {
185 somaxconn = tmp;
186 }
187 } else {
188 somaxconn = tmp;
189 }
190 }
191
192 if (tmp == null) {
193 logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}", file,
194 somaxconn);
195 }
196 }
197 } catch (Exception e) {
198 if (logger.isDebugEnabled()) {
199 logger.debug("Failed to get SOMAXCONN from sysctl and file {}. Default: {}",
200 file, somaxconn, e);
201 }
202 } finally {
203 if (in != null) {
204 try {
205 in.close();
206 } catch (Exception e) {
207
208 }
209 }
210 }
211 return somaxconn;
212 }
213 }
214
215
216
217
218
219
220
221 private static Integer sysctlGetInt(String sysctlKey) throws IOException {
222 Process process = new ProcessBuilder("sysctl", sysctlKey).start();
223 try {
224 InputStream is = process.getInputStream();
225 InputStreamReader isr = new InputStreamReader(is);
226 try (BufferedReader br = new BufferedReader(isr)) {
227 String line = br.readLine();
228 if (line != null && line.startsWith(sysctlKey)) {
229 for (int i = line.length() - 1; i > sysctlKey.length(); --i) {
230 if (!Character.isDigit(line.charAt(i))) {
231 return Integer.valueOf(line.substring(i + 1));
232 }
233 }
234 }
235 return null;
236 }
237 } finally {
238 process.destroy();
239 }
240 }
241
242
243
244
245
246
247
248
249 public static boolean isIpV4StackPreferred() {
250 return IPV4_PREFERRED;
251 }
252
253
254
255
256
257
258
259
260 public static boolean isIpV6AddressesPreferred() {
261 return IPV6_ADDRESSES_PREFERRED;
262 }
263
264
265
266
267 public static byte[] createByteArrayFromIpAddressString(String ipAddressString) {
268
269 if (isValidIpV4Address(ipAddressString)) {
270 return validIpV4ToBytes(ipAddressString);
271 }
272
273 if (isValidIpV6Address(ipAddressString)) {
274 if (ipAddressString.charAt(0) == '[') {
275 ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1);
276 }
277
278 int percentPos = ipAddressString.indexOf('%');
279 if (percentPos >= 0) {
280 ipAddressString = ipAddressString.substring(0, percentPos);
281 }
282
283 return getIPv6ByName(ipAddressString, true);
284 }
285 return null;
286 }
287
288
289
290
291
292 public static InetAddress createInetAddressFromIpAddressString(String ipAddressString) {
293 if (isValidIpV4Address(ipAddressString)) {
294 byte[] bytes = validIpV4ToBytes(ipAddressString);
295 try {
296 return InetAddress.getByAddress(bytes);
297 } catch (UnknownHostException e) {
298
299 throw new IllegalStateException(e);
300 }
301 }
302
303 if (isValidIpV6Address(ipAddressString)) {
304 if (ipAddressString.charAt(0) == '[') {
305 ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1);
306 }
307
308 int percentPos = ipAddressString.indexOf('%');
309 if (percentPos >= 0) {
310 try {
311 int scopeId = Integer.parseInt(ipAddressString.substring(percentPos + 1));
312 ipAddressString = ipAddressString.substring(0, percentPos);
313 byte[] bytes = getIPv6ByName(ipAddressString, true);
314 if (bytes == null) {
315 return null;
316 }
317 try {
318 return Inet6Address.getByAddress(null, bytes, scopeId);
319 } catch (UnknownHostException e) {
320
321 throw new IllegalStateException(e);
322 }
323 } catch (NumberFormatException e) {
324 return null;
325 }
326 }
327 byte[] bytes = getIPv6ByName(ipAddressString, true);
328 if (bytes == null) {
329 return null;
330 }
331 try {
332 return InetAddress.getByAddress(bytes);
333 } catch (UnknownHostException e) {
334
335 throw new IllegalStateException(e);
336 }
337 }
338 return null;
339 }
340
341 private static int decimalDigit(String str, int pos) {
342 return str.charAt(pos) - '0';
343 }
344
345 private static byte ipv4WordToByte(String ip, int from, int toExclusive) {
346 int ret = decimalDigit(ip, from);
347 from++;
348 if (from == toExclusive) {
349 return (byte) ret;
350 }
351 ret = ret * 10 + decimalDigit(ip, from);
352 from++;
353 if (from == toExclusive) {
354 return (byte) ret;
355 }
356 return (byte) (ret * 10 + decimalDigit(ip, from));
357 }
358
359
360 static byte[] validIpV4ToBytes(String ip) {
361 int i;
362 return new byte[] {
363 ipv4WordToByte(ip, 0, i = ip.indexOf('.', 1)),
364 ipv4WordToByte(ip, i + 1, i = ip.indexOf('.', i + 2)),
365 ipv4WordToByte(ip, i + 1, i = ip.indexOf('.', i + 2)),
366 ipv4WordToByte(ip, i + 1, ip.length())
367 };
368 }
369
370
371
372
373 public static int ipv4AddressToInt(Inet4Address ipAddress) {
374 byte[] octets = ipAddress.getAddress();
375
376 return (octets[0] & 0xff) << 24 |
377 (octets[1] & 0xff) << 16 |
378 (octets[2] & 0xff) << 8 |
379 octets[3] & 0xff;
380 }
381
382
383
384
385 public static String intToIpAddress(int i) {
386 StringBuilder buf = new StringBuilder(15);
387 buf.append(i >> 24 & 0xff);
388 buf.append('.');
389 buf.append(i >> 16 & 0xff);
390 buf.append('.');
391 buf.append(i >> 8 & 0xff);
392 buf.append('.');
393 buf.append(i & 0xff);
394 return buf.toString();
395 }
396
397
398
399
400
401
402
403 public static String bytesToIpAddress(byte[] bytes) {
404 return bytesToIpAddress(bytes, 0, bytes.length);
405 }
406
407
408
409
410
411
412
413 public static String bytesToIpAddress(byte[] bytes, int offset, int length) {
414 switch (length) {
415 case 4: {
416 return new StringBuilder(15)
417 .append(bytes[offset] & 0xff)
418 .append('.')
419 .append(bytes[offset + 1] & 0xff)
420 .append('.')
421 .append(bytes[offset + 2] & 0xff)
422 .append('.')
423 .append(bytes[offset + 3] & 0xff).toString();
424 }
425 case 16:
426 return toAddressString(bytes, offset, false);
427 default:
428 throw new IllegalArgumentException("length: " + length + " (expected: 4 or 16)");
429 }
430 }
431
432 public static boolean isValidIpV6Address(String ip) {
433 return isValidIpV6Address((CharSequence) ip);
434 }
435
436 public static boolean isValidIpV6Address(CharSequence ip) {
437 int end = ip.length();
438 if (end < 2) {
439 return false;
440 }
441
442
443 int start;
444 char c = ip.charAt(0);
445 if (c == '[') {
446 end--;
447 if (ip.charAt(end) != ']') {
448
449 return false;
450 }
451 start = 1;
452 c = ip.charAt(1);
453 } else {
454 start = 0;
455 }
456
457 int colons;
458 int compressBegin;
459 if (c == ':') {
460
461 if (ip.charAt(start + 1) != ':') {
462 return false;
463 }
464 colons = 2;
465 compressBegin = start;
466 start += 2;
467 } else {
468 colons = 0;
469 compressBegin = -1;
470 }
471
472 int wordLen = 0;
473 loop:
474 for (int i = start; i < end; i++) {
475 c = ip.charAt(i);
476 if (isValidHexChar(c)) {
477 if (wordLen < 4) {
478 wordLen++;
479 continue;
480 }
481 return false;
482 }
483
484 switch (c) {
485 case ':':
486 if (colons > 7) {
487 return false;
488 }
489 if (ip.charAt(i - 1) == ':') {
490 if (compressBegin >= 0) {
491 return false;
492 }
493 compressBegin = i - 1;
494 } else {
495 wordLen = 0;
496 }
497 colons++;
498 break;
499 case '.':
500
501
502
503 if (compressBegin < 0 && colons != 6 ||
504
505
506 colons == 7 && compressBegin >= start || colons > 7) {
507 return false;
508 }
509
510
511
512
513 int ipv4Start = i - wordLen;
514 int j = ipv4Start - 2;
515 if (isValidIPv4MappedChar(ip.charAt(j))) {
516 if (!isValidIPv4MappedChar(ip.charAt(j - 1)) ||
517 !isValidIPv4MappedChar(ip.charAt(j - 2)) ||
518 !isValidIPv4MappedChar(ip.charAt(j - 3))) {
519 return false;
520 }
521 j -= 5;
522 }
523
524 for (; j >= start; --j) {
525 char tmpChar = ip.charAt(j);
526 if (tmpChar != '0' && tmpChar != ':') {
527 return false;
528 }
529 }
530
531
532 int ipv4End = indexOf(ip, '%', ipv4Start + 7);
533 if (ipv4End < 0) {
534 ipv4End = end;
535 }
536 return isValidIpV4Address(ip, ipv4Start, ipv4End);
537 case '%':
538
539 end = i;
540 break loop;
541 default:
542 return false;
543 }
544 }
545
546
547 if (compressBegin < 0) {
548 return colons == 7 && wordLen > 0;
549 }
550
551 return compressBegin + 2 == end ||
552
553 wordLen > 0 && (colons < 8 || compressBegin <= start);
554 }
555
556 private static boolean isValidIpV4Word(CharSequence word, int from, int toExclusive) {
557 int len = toExclusive - from;
558 char c0, c1, c2;
559 if (len < 1 || len > 3 || (c0 = word.charAt(from)) < '0') {
560 return false;
561 }
562 if (len == 3) {
563 return (c1 = word.charAt(from + 1)) >= '0' &&
564 (c2 = word.charAt(from + 2)) >= '0' &&
565 (c0 <= '1' && c1 <= '9' && c2 <= '9' ||
566 c0 == '2' && c1 <= '5' && (c2 <= '5' || c1 < '5' && c2 <= '9'));
567 }
568 return c0 <= '9' && (len == 1 || isValidNumericChar(word.charAt(from + 1)));
569 }
570
571 private static boolean isValidHexChar(char c) {
572 return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f';
573 }
574
575 private static boolean isValidNumericChar(char c) {
576 return c >= '0' && c <= '9';
577 }
578
579 private static boolean isValidIPv4MappedChar(char c) {
580 return c == 'f' || c == 'F';
581 }
582
583 private static boolean isValidIPv4MappedSeparators(byte b0, byte b1, boolean mustBeZero) {
584
585
586
587 return b0 == b1 && (b0 == 0 || !mustBeZero && b1 == -1);
588 }
589
590 private static boolean isValidIPv4Mapped(byte[] bytes, int currentIndex, int compressBegin, int compressLength) {
591 final boolean mustBeZero = compressBegin + compressLength >= 14;
592 return currentIndex <= 12 && currentIndex >= 2 && (!mustBeZero || compressBegin < 12) &&
593 isValidIPv4MappedSeparators(bytes[currentIndex - 1], bytes[currentIndex - 2], mustBeZero) &&
594 PlatformDependent.isZero(bytes, 0, currentIndex - 3);
595 }
596
597
598
599
600
601
602
603 public static boolean isValidIpV4Address(CharSequence ip) {
604 return isValidIpV4Address(ip, 0, ip.length());
605 }
606
607
608
609
610
611
612
613 public static boolean isValidIpV4Address(String ip) {
614 return isValidIpV4Address(ip, 0, ip.length());
615 }
616
617 private static boolean isValidIpV4Address(CharSequence ip, int from, int toExcluded) {
618 return ip instanceof String ? isValidIpV4Address((String) ip, from, toExcluded) :
619 ip instanceof AsciiString ? isValidIpV4Address((AsciiString) ip, from, toExcluded) :
620 isValidIpV4Address0(ip, from, toExcluded);
621 }
622
623 @SuppressWarnings("DuplicateBooleanBranch")
624 private static boolean isValidIpV4Address(String ip, int from, int toExcluded) {
625 int len = toExcluded - from;
626 int i;
627 return len <= 15 && len >= 7 &&
628 (i = ip.indexOf('.', from + 1)) > 0 && isValidIpV4Word(ip, from, i) &&
629 (i = ip.indexOf('.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
630 (i = ip.indexOf('.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
631 isValidIpV4Word(ip, i + 1, toExcluded);
632 }
633
634 @SuppressWarnings("DuplicateBooleanBranch")
635 private static boolean isValidIpV4Address(AsciiString ip, int from, int toExcluded) {
636 int len = toExcluded - from;
637 int i;
638 return len <= 15 && len >= 7 &&
639 (i = ip.indexOf('.', from + 1)) > 0 && isValidIpV4Word(ip, from, i) &&
640 (i = ip.indexOf('.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
641 (i = ip.indexOf('.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
642 isValidIpV4Word(ip, i + 1, toExcluded);
643 }
644
645 @SuppressWarnings("DuplicateBooleanBranch")
646 private static boolean isValidIpV4Address0(CharSequence ip, int from, int toExcluded) {
647 int len = toExcluded - from;
648 int i;
649 return len <= 15 && len >= 7 &&
650 (i = indexOf(ip, '.', from + 1)) > 0 && isValidIpV4Word(ip, from, i) &&
651 (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
652 (i = indexOf(ip, '.', from = i + 2)) > 0 && isValidIpV4Word(ip, from - 1, i) &&
653 isValidIpV4Word(ip, i + 1, toExcluded);
654 }
655
656
657
658
659
660
661
662
663 public static Inet6Address getByName(CharSequence ip) {
664 return getByName(ip, true);
665 }
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681 public static Inet6Address getByName(CharSequence ip, boolean ipv4Mapped) {
682 byte[] bytes = getIPv6ByName(ip, ipv4Mapped);
683 if (bytes == null) {
684 return null;
685 }
686 try {
687 return Inet6Address.getByAddress(null, bytes, -1);
688 } catch (UnknownHostException e) {
689 throw new RuntimeException(e);
690 }
691 }
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708 static byte[] getIPv6ByName(CharSequence ip, boolean ipv4Mapped) {
709 final byte[] bytes = new byte[IPV6_BYTE_COUNT];
710 final int ipLength = ip.length();
711 int compressBegin = 0;
712 int compressLength = 0;
713 int currentIndex = 0;
714 int value = 0;
715 int begin = -1;
716 int i = 0;
717 int ipv6Separators = 0;
718 int ipv4Separators = 0;
719 int tmp;
720 for (; i < ipLength; ++i) {
721 final char c = ip.charAt(i);
722 switch (c) {
723 case ':':
724 ++ipv6Separators;
725 if (i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR ||
726 ipv4Separators > 0 || ipv6Separators > IPV6_MAX_SEPARATORS ||
727 currentIndex + 1 >= bytes.length) {
728 return null;
729 }
730 value <<= (IPV6_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2;
731
732 if (compressLength > 0) {
733 compressLength -= 2;
734 }
735
736
737
738
739 bytes[currentIndex++] = (byte) (((value & 0xf) << 4) | ((value >> 4) & 0xf));
740 bytes[currentIndex++] = (byte) ((((value >> 8) & 0xf) << 4) | ((value >> 12) & 0xf));
741 tmp = i + 1;
742 if (tmp < ipLength && ip.charAt(tmp) == ':') {
743 ++tmp;
744 if (compressBegin != 0 || (tmp < ipLength && ip.charAt(tmp) == ':')) {
745 return null;
746 }
747 ++ipv6Separators;
748 compressBegin = currentIndex;
749 compressLength = bytes.length - compressBegin - 2;
750 ++i;
751 }
752 value = 0;
753 begin = -1;
754 break;
755 case '.':
756 ++ipv4Separators;
757 tmp = i - begin;
758 if (tmp > IPV4_MAX_CHAR_BETWEEN_SEPARATOR
759 || begin < 0
760 || ipv4Separators > IPV4_SEPARATORS
761 || (ipv6Separators > 0 && (currentIndex + compressLength < 12))
762 || i + 1 >= ipLength
763 || currentIndex >= bytes.length
764 || ipv4Separators == 1 &&
765
766 ((!ipv4Mapped || currentIndex != 0 && !isValidIPv4Mapped(bytes, currentIndex,
767 compressBegin, compressLength)) ||
768 (tmp == 3 && (!isValidNumericChar(ip.charAt(i - 1)) ||
769 !isValidNumericChar(ip.charAt(i - 2)) ||
770 !isValidNumericChar(ip.charAt(i - 3))) ||
771 tmp == 2 && (!isValidNumericChar(ip.charAt(i - 1)) ||
772 !isValidNumericChar(ip.charAt(i - 2))) ||
773 tmp == 1 && !isValidNumericChar(ip.charAt(i - 1))))) {
774 return null;
775 }
776 value <<= (IPV4_MAX_CHAR_BETWEEN_SEPARATOR - tmp) << 2;
777
778
779
780
781 begin = (value & 0xf) * 100 + ((value >> 4) & 0xf) * 10 + ((value >> 8) & 0xf);
782 if (begin > 255) {
783 return null;
784 }
785 bytes[currentIndex++] = (byte) begin;
786 value = 0;
787 begin = -1;
788 break;
789 default:
790 if (!isValidHexChar(c) || (ipv4Separators > 0 && !isValidNumericChar(c))) {
791 return null;
792 }
793 if (begin < 0) {
794 begin = i;
795 } else if (i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR) {
796 return null;
797 }
798
799
800
801
802 value += StringUtil.decodeHexNibble(c) << ((i - begin) << 2);
803 break;
804 }
805 }
806
807 final boolean isCompressed = compressBegin > 0;
808
809 if (ipv4Separators > 0) {
810 if (begin > 0 && i - begin > IPV4_MAX_CHAR_BETWEEN_SEPARATOR ||
811 ipv4Separators != IPV4_SEPARATORS ||
812 currentIndex >= bytes.length) {
813 return null;
814 }
815 if (!(ipv6Separators == 0 || ipv6Separators >= IPV6_MIN_SEPARATORS &&
816 (!isCompressed && (ipv6Separators == 6 && ip.charAt(0) != ':') ||
817 isCompressed && (ipv6Separators < IPV6_MAX_SEPARATORS &&
818 (ip.charAt(0) != ':' || compressBegin <= 2))))) {
819 return null;
820 }
821 value <<= (IPV4_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2;
822
823
824
825
826 begin = (value & 0xf) * 100 + ((value >> 4) & 0xf) * 10 + ((value >> 8) & 0xf);
827 if (begin > 255) {
828 return null;
829 }
830 bytes[currentIndex++] = (byte) begin;
831 } else {
832 tmp = ipLength - 1;
833 if (begin > 0 && i - begin > IPV6_MAX_CHAR_BETWEEN_SEPARATOR ||
834 ipv6Separators < IPV6_MIN_SEPARATORS ||
835 !isCompressed && (ipv6Separators + 1 != IPV6_MAX_SEPARATORS ||
836 ip.charAt(0) == ':' || ip.charAt(tmp) == ':') ||
837 isCompressed && (ipv6Separators > IPV6_MAX_SEPARATORS ||
838 (ipv6Separators == IPV6_MAX_SEPARATORS &&
839 (compressBegin <= 2 && ip.charAt(0) != ':' ||
840 compressBegin >= 14 && ip.charAt(tmp) != ':'))) ||
841 currentIndex + 1 >= bytes.length ||
842 begin < 0 && ip.charAt(tmp - 1) != ':' ||
843 compressBegin > 2 && ip.charAt(0) == ':') {
844 return null;
845 }
846 if (begin >= 0 && i - begin <= IPV6_MAX_CHAR_BETWEEN_SEPARATOR) {
847 value <<= (IPV6_MAX_CHAR_BETWEEN_SEPARATOR - (i - begin)) << 2;
848 }
849
850
851
852 bytes[currentIndex++] = (byte) (((value & 0xf) << 4) | ((value >> 4) & 0xf));
853 bytes[currentIndex++] = (byte) ((((value >> 8) & 0xf) << 4) | ((value >> 12) & 0xf));
854 }
855
856 if (currentIndex < bytes.length) {
857 int toBeCopiedLength = currentIndex - compressBegin;
858 int targetIndex = bytes.length - toBeCopiedLength;
859 System.arraycopy(bytes, compressBegin, bytes, targetIndex, toBeCopiedLength);
860
861 Arrays.fill(bytes, compressBegin, targetIndex, (byte) 0);
862 }
863
864 if (ipv4Separators > 0) {
865
866
867
868 bytes[10] = bytes[11] = (byte) 0xff;
869 }
870
871 return bytes;
872 }
873
874
875
876
877
878
879
880
881 public static String toSocketAddressString(InetSocketAddress addr) {
882 String port = String.valueOf(addr.getPort());
883 final StringBuilder sb;
884
885 if (addr.isUnresolved()) {
886 String hostname = getHostname(addr);
887 sb = newSocketAddressStringBuilder(hostname, port, !isValidIpV6Address(hostname));
888 } else {
889 InetAddress address = addr.getAddress();
890 String hostString = toAddressString(address);
891 sb = newSocketAddressStringBuilder(hostString, port, address instanceof Inet4Address);
892 }
893 return sb.append(':').append(port).toString();
894 }
895
896
897
898
899 public static String toSocketAddressString(String host, int port) {
900 String portStr = String.valueOf(port);
901 return newSocketAddressStringBuilder(
902 host, portStr, !isValidIpV6Address(host)).append(':').append(portStr).toString();
903 }
904
905 private static StringBuilder newSocketAddressStringBuilder(String host, String port, boolean ipv4) {
906 int hostLen = host.length();
907 if (ipv4) {
908
909 return new StringBuilder(hostLen + 1 + port.length()).append(host);
910 }
911
912 StringBuilder stringBuilder = new StringBuilder(hostLen + 3 + port.length());
913 if (hostLen > 1 && host.charAt(0) == '[' && host.charAt(hostLen - 1) == ']') {
914 return stringBuilder.append(host);
915 }
916 return stringBuilder.append('[').append(host).append(']');
917 }
918
919
920
921
922
923
924
925
926
927
928
929
930
931 public static String toAddressString(InetAddress ip) {
932 return toAddressString(ip, false);
933 }
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959 public static String toAddressString(InetAddress ip, boolean ipv4Mapped) {
960 if (ip instanceof Inet4Address) {
961 return ip.getHostAddress();
962 }
963 if (!(ip instanceof Inet6Address)) {
964 throw new IllegalArgumentException("Unhandled type: " + ip);
965 }
966
967 return toAddressString(ip.getAddress(), 0, ipv4Mapped);
968 }
969
970 private static String toAddressString(byte[] bytes, int offset, boolean ipv4Mapped) {
971 final int[] words = new int[IPV6_WORD_COUNT];
972 int i;
973 final int end = offset + words.length;
974 for (i = offset; i < end; ++i) {
975 words[i] = ((bytes[i << 1] & 0xff) << 8) | (bytes[(i << 1) + 1] & 0xff);
976 }
977
978
979 int currentStart = -1;
980 int currentLength;
981 int shortestStart = -1;
982 int shortestLength = 0;
983 for (i = 0; i < words.length; ++i) {
984 if (words[i] == 0) {
985 if (currentStart < 0) {
986 currentStart = i;
987 }
988 } else if (currentStart >= 0) {
989 currentLength = i - currentStart;
990 if (currentLength > shortestLength) {
991 shortestStart = currentStart;
992 shortestLength = currentLength;
993 }
994 currentStart = -1;
995 }
996 }
997
998 if (currentStart >= 0) {
999 currentLength = i - currentStart;
1000 if (currentLength > shortestLength) {
1001 shortestStart = currentStart;
1002 shortestLength = currentLength;
1003 }
1004 }
1005
1006 if (shortestLength == 1) {
1007 shortestLength = 0;
1008 shortestStart = -1;
1009 }
1010
1011
1012 final int shortestEnd = shortestStart + shortestLength;
1013 final StringBuilder b = new StringBuilder(IPV6_MAX_CHAR_COUNT);
1014 if (shortestEnd < 0) {
1015 b.append(Integer.toHexString(words[0]));
1016 for (i = 1; i < words.length; ++i) {
1017 b.append(':');
1018 b.append(Integer.toHexString(words[i]));
1019 }
1020 } else {
1021
1022 final boolean isIpv4Mapped;
1023 if (inRangeEndExclusive(0, shortestStart, shortestEnd)) {
1024 b.append("::");
1025 isIpv4Mapped = ipv4Mapped && (shortestEnd == 5 && words[5] == 0xffff);
1026 } else {
1027 b.append(Integer.toHexString(words[0]));
1028 isIpv4Mapped = false;
1029 }
1030 for (i = 1; i < words.length; ++i) {
1031 if (!inRangeEndExclusive(i, shortestStart, shortestEnd)) {
1032 if (!inRangeEndExclusive(i - 1, shortestStart, shortestEnd)) {
1033
1034 if (!isIpv4Mapped || i == 6) {
1035 b.append(':');
1036 } else {
1037 b.append('.');
1038 }
1039 }
1040 if (isIpv4Mapped && i > 5) {
1041 b.append(words[i] >> 8);
1042 b.append('.');
1043 b.append(words[i] & 0xff);
1044 } else {
1045 b.append(Integer.toHexString(words[i]));
1046 }
1047 } else if (!inRangeEndExclusive(i - 1, shortestStart, shortestEnd)) {
1048
1049 b.append("::");
1050 }
1051 }
1052 }
1053
1054 return b.toString();
1055 }
1056
1057
1058
1059
1060
1061
1062
1063 public static String getHostname(InetSocketAddress addr) {
1064 return addr.getHostString();
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074 public static boolean isFamilySupported(InetAddress address, ProtocolFamily family) {
1075 return isFamilySupported(address.getClass(), family);
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085 public static boolean isFamilySupported(Class<? extends InetAddress> addressType, ProtocolFamily family) {
1086 return family(addressType) == family;
1087 }
1088
1089
1090
1091
1092
1093
1094
1095 public static Class<? extends InetAddress> addressType(ProtocolFamily family) {
1096 if (family == StandardProtocolFamily.INET) {
1097 return Inet4Address.class;
1098 }
1099 if (family == StandardProtocolFamily.INET6) {
1100 return Inet6Address.class;
1101 }
1102 return null;
1103 }
1104
1105
1106
1107
1108
1109
1110
1111 public static ProtocolFamily family(InetAddress address) {
1112 return family(address.getClass());
1113 }
1114
1115
1116
1117
1118
1119
1120
1121 public static ProtocolFamily family(Class<? extends InetAddress> addressType) {
1122 if (Inet4Address.class.isAssignableFrom(addressType)) {
1123 return StandardProtocolFamily.INET;
1124 }
1125 if (Inet6Address.class.isAssignableFrom(addressType)) {
1126 return StandardProtocolFamily.INET6;
1127 }
1128 return null;
1129 }
1130
1131
1132
1133
1134
1135
1136
1137 public static InetAddress localHost(ProtocolFamily family) {
1138 if (family == StandardProtocolFamily.INET) {
1139 return NetUtil.LOCALHOST4;
1140 }
1141 if (family == StandardProtocolFamily.INET6) {
1142 return NetUtil.LOCALHOST6;
1143 }
1144 return NetUtil.LOCALHOST;
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 private static boolean inRangeEndExclusive(int value, int start, int end) {
1159 return value >= start && value < end;
1160 }
1161
1162
1163
1164
1165 private NetUtil() {
1166
1167 }
1168 }