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