InetAddress.java revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.net; 19 20import java.io.FileDescriptor; 21import java.io.IOException; 22import java.io.ObjectInputStream; 23import java.io.ObjectOutputStream; 24import java.io.ObjectStreamException; 25import java.io.ObjectStreamField; 26import java.io.Serializable; 27import java.security.AccessController; 28import java.util.ArrayList; 29import java.util.Enumeration; 30import java.util.StringTokenizer; 31 32import org.apache.harmony.luni.net.NetUtil; 33import org.apache.harmony.luni.platform.INetworkSystem; 34import org.apache.harmony.luni.platform.Platform; 35import org.apache.harmony.luni.util.Inet6Util; 36import org.apache.harmony.luni.util.Msg; 37import org.apache.harmony.luni.util.PriviAction; 38 39/** 40 * The Internet Protocol (IP) address representation class. This class 41 * encapsulates an IP address and provides name and reverse name resolution 42 * functions. The address is stored in network order, but as a signed (rather 43 * than unsigned) integer. 44 * 45 * @since Android 1.0 46 */ 47public class InetAddress extends Object implements Serializable { 48 49 final static byte[] any_bytes = { 0, 0, 0, 0 }; 50 51 final static byte[] localhost_bytes = { 127, 0, 0, 1 }; 52 53 static InetAddress ANY = new Inet4Address(any_bytes); 54 55 private final static INetworkSystem NETIMPL = Platform.getNetworkSystem(); 56 57 final static InetAddress LOOPBACK = new Inet4Address(localhost_bytes, 58 "localhost"); //$NON-NLS-1$ 59 60 private static final String ERRMSG_CONNECTION_REFUSED = "Connection refused"; //$NON-NLS-1$ 61 62 private static final long serialVersionUID = 3286316764910316507L; 63 64 // BEGIN android-added 65 /** 66 * default time-to-live for DNS cache entries; 600 seconds == 10 minutes 67 */ 68 private static final String DEFAULT_NETADDR_CACHE_TTL_SECS = "600"; 69 // END android-added 70 71 String hostName; 72 73 private static class WaitReachable { 74 } 75 76 private transient Object waitReachable = new WaitReachable(); 77 78 private boolean reached; 79 80 private int addrCount; 81 82 int family = 2; 83 84 byte[] ipaddress; 85 86 // BEGIN android-removed 87 // // Fill in the JNI id caches 88 // private static native void oneTimeInitialization(boolean supportsIPv6); 89 // 90 // static { 91 // oneTimeInitialization(true); 92 // } 93 // END android-removed 94 95 /** 96 * Constructs an InetAddress. 97 */ 98 InetAddress() { 99 super(); 100 } 101 102 /** 103 * Constructs an {@code InetAddress}, representing the {@code address} and 104 * {@code hostName}. 105 * 106 * @param address 107 * the network address. 108 */ 109 InetAddress(byte[] address) { 110 super(); 111 this.ipaddress = address; 112 } 113 114 /** 115 * Constructs an {@code InetAddress}, representing the {@code address} and 116 * {@code hostName}. 117 * 118 * @param address 119 * the network address. 120 */ 121 InetAddress(byte[] address, String hostName) { 122 super(); 123 this.ipaddress = address; 124 this.hostName = hostName; 125 } 126 127 // BEGIN android-removed 128 // Removed in newer version of harmony 129 // /** 130 // * Returns the IP address of the argument {@code addr} as a byte array. The 131 // * elements are in network order (the highest order address byte is in the 132 // * zeroth element). 133 // * 134 // * @return the network address as a byte array. 135 // */ 136 // static byte[] addressOf(int addr) { 137 // int temp = addr; 138 // byte array[] = new byte[4]; 139 // array[3] = (byte) (temp & 0xFF); 140 // array[2] = (byte) ((temp >>>= 8) & 0xFF); 141 // array[1] = (byte) ((temp >>>= 8) & 0xFF); 142 // array[0] = (byte) ((temp >>>= 8) & 0xFF); 143 // return array; 144 // } 145 // BEGIN android-removed 146 147 CacheElement cacheElement() { 148 return new CacheElement(); 149 } 150 151 /** 152 * Compares this {@code InetAddress} instance against the specified address 153 * in {@code obj}. Two addresses are equal if their address byte arrays have 154 * the same length and if the bytes in the arrays are equal. 155 * 156 * @param obj 157 * the object to be tested for equality. 158 * @return {@code true} if both objects are equal, {@code false} otherwise. 159 * @since Android 1.0 160 */ 161 @Override 162 public boolean equals(Object obj) { 163 // BEGIN android-changed 164 if (!(obj instanceof InetAddress)) { 165 return false; 166 } 167 // END android-changed 168 169 // now check if their byte arrays match... 170 byte[] objIPaddress = ((InetAddress) obj).ipaddress; 171 // BEGIN android-added 172 if (objIPaddress.length != ipaddress.length) { 173 return false; 174 } 175 // END android-added 176 for (int i = 0; i < objIPaddress.length; i++) { 177 if (objIPaddress[i] != this.ipaddress[i]) { 178 return false; 179 } 180 } 181 return true; 182 } 183 184 /** 185 * Returns the IP address represented by this {@code InetAddress} instance 186 * as a byte array. The elements are in network order (the highest order 187 * address byte is in the zeroth element). 188 * 189 * @return the address in form of a byte array. 190 * @since Android 1.0 191 */ 192 public byte[] getAddress() { 193 return ipaddress.clone(); 194 } 195 196 /** 197 * Gets all IP addresses associated with the given {@code host} identified 198 * by name or IP address in dot-notation. The IP address is resolved by the 199 * configured name service. If the host name is empty or {@code null} an 200 * {@code UnknownHostException} is thrown. If the host name is a dotted IP 201 * address string an array with the corresponding single {@code InetAddress} 202 * is returned. 203 * 204 * @param host 205 * the host's name or IP to be resolved to an address. 206 * @return the array of addresses associated with the specified host. 207 * @throws UnknownHostException 208 * if the address lookup fails. 209 * @since Android 1.0 210 */ 211 public static InetAddress[] getAllByName(String host) 212 throws UnknownHostException { 213 // BEGIN android-changed 214 // Added change taken from newer harmony concerning zero length hostname. 215 // Added special handling for localhost, since it doesn't work properly. 216 // TODO Get rid of this later... 217 if (host == null || 0 == host.length() || 218 "localhost".equalsIgnoreCase(host)) { 219 return new InetAddress[] { preferIPv6Addresses() 220 ? Inet6Address.LOOPBACK 221 : LOOPBACK }; 222 } 223 // END android-changed 224 225 if (isHostName(host)) { 226 SecurityManager security = System.getSecurityManager(); 227 if (security != null) { 228 security.checkConnect(host, -1); 229 } 230 // BEGIN android-changed 231 byte[][] rawAddresses = getallbyname(host, 232 Socket.preferIPv4Stack()); 233 InetAddress[] returnedAddresses = new 234 InetAddress[rawAddresses.length]; 235 for (int i = 0; i < rawAddresses.length; i++) { 236 byte[] rawAddress = rawAddresses[i]; 237 if (rawAddress.length == 16) { 238 returnedAddresses[i] = new Inet6Address(rawAddress, host); 239 } else if (rawAddress.length == 4) { 240 returnedAddresses[i] = new Inet4Address(rawAddress, host); 241 } else { 242 // Cannot happen, because the underlying code only returns 243 // addresses that are 4 or 16 bytes long. 244 throw new AssertionError("Impossible address length " + 245 rawAddress.length); 246 } 247 } 248 249 // ok we may have to re-order to make sure the 250 // preferIPv6Addresses is respected 251 // END android-changed 252 InetAddress[] orderedAddresses = null; 253 if (returnedAddresses != null) { 254 orderedAddresses = new InetAddress[returnedAddresses.length]; 255 int curPosition = 0; 256 if (InetAddress.preferIPv6Addresses()) { 257 for (int i = 0; i < returnedAddresses.length; i++) { 258 if (returnedAddresses[i] instanceof Inet6Address) { 259 orderedAddresses[curPosition] = returnedAddresses[i]; 260 curPosition++; 261 } 262 } 263 for (int i = 0; i < returnedAddresses.length; i++) { 264 // BEGIN android-changed 265 if (!(returnedAddresses[i] instanceof Inet6Address)) { 266 // END android-changed 267 orderedAddresses[curPosition] = returnedAddresses[i]; 268 curPosition++; 269 } 270 } 271 } else { 272 for (int i = 0; i < returnedAddresses.length; i++) { 273 // BEGIN android-changed 274 if (!(returnedAddresses[i] instanceof Inet6Address)) { 275 // END android-changed 276 orderedAddresses[curPosition] = returnedAddresses[i]; 277 curPosition++; 278 } 279 } 280 for (int i = 0; i < returnedAddresses.length; i++) { 281 if (returnedAddresses[i] instanceof Inet6Address) { 282 orderedAddresses[curPosition] = returnedAddresses[i]; 283 curPosition++; 284 } 285 } 286 } 287 } 288 return orderedAddresses; 289 } 290 291 byte[] hBytes = Inet6Util.createByteArrayFromIPAddressString(host); 292 // BEGIN android-added 293 // Copied from a newer version of harmony 294 if (hBytes.length == 4) { 295 return (new InetAddress[] { new Inet4Address(hBytes) }); 296 } else if (hBytes.length == 16) { 297 return (new InetAddress[] { new Inet6Address(hBytes) }); 298 } 299 // END android-added 300 return (new InetAddress[] { new InetAddress(hBytes) }); 301 } 302 303 /** 304 * Returns the address of a host according to the given host string name 305 * {@code host}. The host string may be either a machine name or a dotted 306 * string IP address. If the latter, the {@code hostName} field is 307 * determined upon demand. {@code host} can be {@code null} which means that 308 * an address of the loopback interface is returned. 309 * 310 * @param host 311 * the hostName to be resolved to an address or {@code null}. 312 * @return the {@code InetAddress} instance representing the host. 313 * @throws UnknownHostException 314 * if the address lookup fails. 315 * @since Android 1.0 316 */ 317 public static InetAddress getByName(String host) 318 throws UnknownHostException { 319 // BEGIN android-changed 320 // Added special handling for localhost, since it doesn't work properly. 321 // TODO Get rid of this later... 322 if (host == null || 0 == host.length() || 323 "localhost".equalsIgnoreCase(host)) { 324 return InetAddress.LOOPBACK; 325 } 326 // END android-changed 327 if (host.equals("0")) { //$NON-NLS-1$ 328 return InetAddress.ANY; 329 } 330 331 if (isHostName(host)) { 332 SecurityManager security = System.getSecurityManager(); 333 if (security != null) { 334 security.checkConnect(host, -1); 335 } 336 return lookupHostByName(host); 337 } 338 339 return createHostNameFromIPAddress(host); 340 } 341 342 /** 343 * Gets the textual representation of this IP address. 344 * 345 * @return the textual representation of this host address in form of a 346 * dotted string. 347 * @since Android 1.0 348 */ 349 public String getHostAddress() { 350 return inetNtoaImpl(bytesToInt(ipaddress, 0)); 351 } 352 353 /** 354 * Gets the host name of this IP address. If the IP address could not be 355 * resolved, the textual representation in a dotted-quad-notation is 356 * returned. 357 * 358 * @return the corresponding string name of this IP address. 359 * @since Android 1.0 360 */ 361 public String getHostName() { 362 try { 363 if (hostName == null) { 364 int address = 0; 365 if (ipaddress.length == 4) { 366 address = bytesToInt(ipaddress, 0); 367 if (address == 0) { 368 return hostName = inetNtoaImpl(address); 369 } 370 } 371 hostName = getHostByAddrImpl(ipaddress).hostName; 372 if (hostName.equals("localhost") && ipaddress.length == 4 //$NON-NLS-1$ 373 && address != 0x7f000001) { 374 return hostName = inetNtoaImpl(address); 375 } 376 } 377 } catch (UnknownHostException e) { 378 return hostName = Inet6Util 379 .createIPAddrStringFromByteArray(ipaddress); 380 } 381 SecurityManager security = System.getSecurityManager(); 382 try { 383 // Only check host names, not addresses 384 if (security != null && isHostName(hostName)) { 385 security.checkConnect(hostName, -1); 386 } 387 } catch (SecurityException e) { 388 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 389 } 390 return hostName; 391 } 392 393 /** 394 * Gets the fully qualified domain name for the host associated with this IP 395 * address. If a security manager is set, it is checked if the method caller 396 * is allowed to get the hostname. Otherwise, the textual representation in 397 * a dotted-quad-notation is returned. 398 * 399 * @return the fully qualified domain name of this IP address. 400 * @since Android 1.0 401 */ 402 public String getCanonicalHostName() { 403 String canonicalName; 404 try { 405 int address = 0; 406 if (ipaddress.length == 4) { 407 address = bytesToInt(ipaddress, 0); 408 if (address == 0) { 409 return inetNtoaImpl(address); 410 } 411 } 412 canonicalName = getHostByAddrImpl(ipaddress).hostName; 413 } catch (UnknownHostException e) { 414 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 415 } 416 SecurityManager security = System.getSecurityManager(); 417 try { 418 // Only check host names, not addresses 419 if (security != null && isHostName(canonicalName)) { 420 security.checkConnect(canonicalName, -1); 421 } 422 } catch (SecurityException e) { 423 return Inet6Util.createIPAddrStringFromByteArray(ipaddress); 424 } 425 return canonicalName; 426 } 427 428 /** 429 * Gets the local host address if the security policy allows this. 430 * Otherwise, gets the loopback address which allows this machine to be 431 * contacted. 432 * <p> 433 * The current implementation returns always the loopback address. 434 * </p> 435 * 436 * @return the {@code InetAddress} representing the local host. 437 * @throws UnknownHostException 438 * if the address lookup fails. 439 * @since Android 1.0 440 */ 441 public static InetAddress getLocalHost() throws UnknownHostException { 442 String host = getHostNameImpl(); 443 SecurityManager security = System.getSecurityManager(); 444 try { 445 if (security != null) { 446 security.checkConnect(host, -1); 447 } 448 } catch (SecurityException e) { 449 return InetAddress.LOOPBACK; 450 } 451 return lookupHostByName(host); 452 } 453 454 /** 455 * Gets the hashcode of the represented IP address. 456 * 457 * @return the appropriate hashcode value. 458 * @since Android 1.0 459 */ 460 @Override 461 public int hashCode() { 462 return bytesToInt(ipaddress, 0); 463 } 464 465 /** 466 * Returns whether this address is an IP multicast address or not. 467 * 468 * @return {@code true} if this address is in the multicast group, {@code 469 * false} otherwise. 470 * @since Android 1.0 471 */ 472 public boolean isMulticastAddress() { 473 return ((ipaddress[0] & 255) >>> 4) == 0xE; 474 } 475 476 static synchronized InetAddress lookupHostByName(String host) 477 throws UnknownHostException { 478 int ttl = -1; 479 480 // BEGIN android-changed 481 String ttlValue = AccessController 482 .doPrivileged(new PriviAction<String>( 483 "networkaddress.cache.ttl", DEFAULT_NETADDR_CACHE_TTL_SECS)); //$NON-NLS-1$ 484 // END android-changed 485 try { 486 if (ttlValue != null) { 487 ttl = Integer.decode(ttlValue).intValue(); 488 } 489 } catch (NumberFormatException e) { 490 // Ignored 491 } 492 CacheElement element = null; 493 if (ttl == 0) { 494 Cache.clear(); 495 } else { 496 element = Cache.get(host); 497 // BEGIN android-changed 498 if (element != null && ttl > 0) { 499 long delta = System.nanoTime() - element.nanoTimeAdded; 500 if (delta > secondsToNanos(ttl)) { 501 element = null; 502 } 503 } 504 // END android-changed 505 } 506 if (element != null) { 507 return element.inetAddress(); 508 } 509 510 // now try the negative cache 511 String failedMessage = NegativeCache.getFailedMessage(host); 512 if (failedMessage != null) { 513 throw new UnknownHostException(host + " - " + failedMessage); //$NON-NLS-1$ 514 } 515 516 InetAddress anInetAddress; 517 try { 518 anInetAddress = getHostByNameImpl(host, preferIPv6Addresses()); 519 } catch (UnknownHostException e) { 520 // put the entry in the negative cache 521 NegativeCache.put(host, e.getMessage()); 522 throw new UnknownHostException(host + " - " + e.getMessage()); //$NON-NLS-1$ 523 } 524 525 Cache.add(anInetAddress); 526 return anInetAddress; 527 } 528 529 // BEGIN android-added 530 /** 531 * Multiplies value by 1 billion. 532 */ 533 private static long secondsToNanos(int ttl) { 534 return (long) ttl * 1000000000; 535 } 536 // END android-added 537 538 // BEGIN android-deleted 539 // static native InetAddress[] getAliasesByNameImpl(String name) 540 // throws UnknownHostException; 541 // END android-deleted 542 543 // BEGIN android-changed 544 /** 545 * Resolves a host name to its IP addresses. Thread safe. 546 */ 547 private static native byte[][] getallbyname(String name, 548 boolean preferIPv4Stack); 549 // END android-changed 550 551 /** 552 * Query the IP stack for the host address. The host is in address form. 553 * 554 * @param addr 555 * the host address to lookup. 556 * @throws UnknownHostException 557 * if an error occurs during lookup. 558 */ 559 // BEGIN android-changed 560 // static native InetAddress getHostByAddrImpl(byte[] addr) 561 // throws UnknownHostException; 562 static InetAddress getHostByAddrImpl(byte[] addr) 563 throws UnknownHostException { 564 return new InetAddress(addr, gethostbyaddr(addr)); 565 } 566 567 /** 568 * Resolves an IP address to a hostname. Thread safe. 569 */ 570 private static native String gethostbyaddr(byte[] addr); 571 // END android-changed 572 573 static int inetAddr(String host) throws UnknownHostException { 574 return (host.equals("255.255.255.255")) ? 0xFFFFFFFF //$NON-NLS-1$ 575 : inetAddrImpl(host); 576 } 577 578 /** 579 * Convert a string containing an IPv4 Internet Protocol dotted address into 580 * a binary address. Note, the special case of '255.255.255.255' throws an 581 * exception, so this value should not be used as an argument. See also 582 * inetAddr(String). 583 */ 584 // BEGIN android-changed 585 // static native int inetAddrImpl(String host) throws UnknownHostException; 586 static int inetAddrImpl(String host) throws UnknownHostException { 587 // TODO Probably not exactly what we want, and also inefficient. Provide native later. 588 try { 589 String[] args = host.split("\\."); 590 591 int a = Integer.parseInt(args[0]) << 24; 592 int b = Integer.parseInt(args[1]) << 16; 593 int c = Integer.parseInt(args[2]) << 8; 594 int d = Integer.parseInt(args[3]) ; 595 596 return a | b | c | d; 597 } catch (Exception ex) { 598 throw new UnknownHostException(host); 599 } 600 } 601 // END android-changed 602 603 /** 604 * Convert a binary address into a string containing an Ipv4 Internet 605 * Protocol dotted address. 606 */ 607 // BEGIN android-changed 608 // static native String inetNtoaImpl(int hipAddr); 609 static String inetNtoaImpl(int hipAddr) { 610 // TODO Inefficient and probably wrong. Provide proper (native?) implementation later. 611 int a = (hipAddr >> 24) & 0xFF; 612 int b = (hipAddr >> 16) & 0xFF; 613 int c = (hipAddr >> 8) & 0xFF; 614 int d = (hipAddr ) & 0xFF; 615 616 return "" + a + "." + b + "." + c + "." + d; 617 } 618 // END android-changed 619 620 /** 621 * Query the IP stack for the host address. The host is in string name form. 622 * 623 * @param name 624 * the host name to lookup 625 * @param preferIPv6Addresses 626 * address preference if underlying platform is V4/V6 627 * @return InetAddress the host address 628 * @throws UnknownHostException 629 * if an error occurs during lookup 630 */ 631 // BEGIN android-changed 632 // static native InetAddress getHostByNameImpl(String name, 633 // boolean preferIPv6Address) throws UnknownHostException; 634 static InetAddress getHostByNameImpl(String name, 635 boolean preferIPv6Address) throws UnknownHostException { 636 // TODO Mapped Harmony to Android native. Get rid of indirection later. 637 return getAllByName(name)[0]; 638 } 639 // END android-changed 640 641 /** 642 * Gets the host name of the system. 643 * 644 * @return String the system hostname 645 */ 646 // BEGIN android-changed 647 static String getHostNameImpl() { 648 // TODO Mapped Harmony to Android native. Get rid of indirection later. 649 650 return gethostname(); 651 } 652 static native String gethostname(); 653 // END android-changed 654 655 static String getHostNameInternal(String host) throws UnknownHostException { 656 if (host == null || 0 == host.length()) { 657 return InetAddress.LOOPBACK.getHostAddress(); 658 } 659 if (isHostName(host)) { 660 return lookupHostByName(host).getHostAddress(); 661 } 662 return host; 663 } 664 665 /** 666 * Returns a string containing a concise, human-readable description of this 667 * IP address. 668 * 669 * @return the description, as host/address. 670 * @since Android 1.0 671 */ 672 @Override 673 public String toString() { 674 return (hostName == null ? "" : hostName) + "/" + getHostAddress(); //$NON-NLS-1$ //$NON-NLS-2$ 675 } 676 677 class CacheElement { 678 // BEGIN android-changed 679 // Partly copied from a newer version of harmony 680 final long nanoTimeAdded = System.nanoTime(); 681 682 CacheElement next; 683 684 CacheElement() { 685 super(); 686 } 687 // END android-changed 688 689 String hostName() { 690 return hostName; 691 } 692 693 InetAddress inetAddress() { 694 return InetAddress.this; 695 } 696 } 697 698 // BEGIN android-changed 699 // Copied from a newer version of harmony 700 static class Cache { 701 private static int maxSize = 5; 702 703 private static int size = 0; 704 705 private static CacheElement head; 706 707 static synchronized void clear() { 708 size = 0; 709 head = null; 710 } 711 712 static synchronized void add(InetAddress value) { 713 CacheElement newElement = value.cacheElement(); 714 if (size < maxSize) { 715 size++; 716 } else { 717 deleteTail(); 718 } 719 newElement.next = head; // If the head is null, this does no harm. 720 head = newElement; 721 } 722 723 static synchronized CacheElement get(String name) { 724 CacheElement previous = null; 725 CacheElement current = head; 726 boolean notFound = true; 727 while ((null != current) 728 && (notFound = !(name.equals(current.hostName())))) { 729 previous = current; 730 current = current.next; 731 } 732 if (notFound) { 733 return null; 734 } 735 moveToHead(current, previous); 736 return current; 737 } 738 739 private synchronized static void deleteTail() { 740 if (0 == size) { 741 return; 742 } 743 if (1 == size) { 744 head = null; 745 } 746 747 CacheElement previous = null; 748 CacheElement current = head; 749 while (null != current.next) { 750 previous = current; 751 current = current.next; 752 } 753 previous.next = null; 754 } 755 756 private synchronized static void moveToHead(CacheElement element, 757 CacheElement elementPredecessor) { 758 if (null == elementPredecessor) { 759 head = element; 760 } else { 761 elementPredecessor.next = element.next; 762 element.next = head; 763 head = element; 764 } 765 } 766 } 767 // END android-changed 768 769 /** 770 * Returns true if the string is a host name, false if it is an IP Address. 771 */ 772 private static boolean isHostName(String value) { 773 return !(Inet6Util.isValidIPV4Address(value) || Inet6Util 774 .isValidIP6Address(value)); 775 } 776 777 /** 778 * Returns whether this address is a loopback address or not. This 779 * implementation returns always {@code false}. Valid IPv4 loopback 780 * addresses are 127.d.d.d The only valid IPv6 loopback address is ::1. 781 * 782 * @return {@code true} if this instance represents a loopback address, 783 * {@code false} otherwise. 784 * @since Android 1.0 785 */ 786 public boolean isLoopbackAddress() { 787 return false; 788 } 789 790 /** 791 * Returns whether this address is a link-local address or not. This 792 * implementation returns always {@code false}. 793 * <p> 794 * Valid IPv6 link-local addresses are FE80::0 through to 795 * FEBF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. 796 * </p> 797 * <p> 798 * There are no valid IPv4 link-local addresses. 799 * </p> 800 * 801 * @return {@code true} if this instance represents a link-local address, 802 * {@code false} otherwise. 803 * @since Android 1.0 804 */ 805 public boolean isLinkLocalAddress() { 806 return false; 807 } 808 809 /** 810 * Returns whether this address is a site-local address or not. This 811 * implementation returns always {@code false}. 812 * <p> 813 * Valid IPv6 site-local addresses are FEC0::0 through to 814 * FEFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF. 815 * </p> 816 * <p> 817 * There are no valid IPv4 site-local addresses. 818 * </p> 819 * 820 * @return {@code true} if this instance represents a site-local address, 821 * {@code false} otherwise. 822 * @since Android 1.0 823 */ 824 public boolean isSiteLocalAddress() { 825 return false; 826 } 827 828 /** 829 * Returns whether this address is a global multicast address or not. This 830 * implementation returns always {@code false}. 831 * <p> 832 * Valid IPv6 link-global multicast addresses are FFxE:/112 where x is a set 833 * of flags, and the additional 112 bits make up the global multicast 834 * address space. 835 * </p> 836 * <p> 837 * Valid IPv4 global multicast addresses are between: 224.0.1.0 to 838 * 238.255.255.255. 839 * </p> 840 * 841 * @return {@code true} if this instance represents a global multicast 842 * address, {@code false} otherwise. 843 * @since Android 1.0 844 */ 845 public boolean isMCGlobal() { 846 return false; 847 } 848 849 /** 850 * Returns whether this address is a node-local multicast address or not. 851 * This implementation returns always {@code false}. 852 * <p> 853 * Valid IPv6 node-local multicast addresses are FFx1:/112 where x is a set 854 * of flags, and the additional 112 bits make up the node-local multicast 855 * address space. 856 * </p> 857 * <p> 858 * There are no valid IPv4 node-local multicast addresses. 859 * </p> 860 * 861 * @return {@code true} if this instance represents a node-local multicast 862 * address, {@code false} otherwise. 863 * @since Android 1.0 864 */ 865 public boolean isMCNodeLocal() { 866 return false; 867 } 868 869 /** 870 * Returns whether this address is a link-local multicast address or not. 871 * This implementation returns always {@code false}. 872 * <p> 873 * Valid IPv6 link-local multicast addresses are FFx2:/112 where x is a set 874 * of flags, and the additional 112 bits make up the link-local multicast 875 * address space. 876 * </p> 877 * <p> 878 * Valid IPv4 link-local addresses are between: 224.0.0.0 to 224.0.0.255 879 * </p> 880 * 881 * @return {@code true} if this instance represents a link-local multicast 882 * address, {@code false} otherwise. 883 * @since Android 1.0 884 */ 885 public boolean isMCLinkLocal() { 886 return false; 887 } 888 889 /** 890 * Returns whether this address is a site-local multicast address or not. 891 * This implementation returns always {@code false}. 892 * <p> 893 * Valid IPv6 site-local multicast addresses are FFx5:/112 where x is a set 894 * of flags, and the additional 112 bits make up the site-local multicast 895 * address space. 896 * </p> 897 * <p> 898 * Valid IPv4 site-local addresses are between: 239.252.0.0 to 899 * 239.255.255.255 900 * </p> 901 * 902 * @return {@code true} if this instance represents a site-local multicast 903 * address, {@code false} otherwise. 904 * @since Android 1.0 905 */ 906 public boolean isMCSiteLocal() { 907 return false; 908 } 909 910 /** 911 * Returns whether this address is a organization-local multicast address or 912 * not. This implementation returns always {@code false}. 913 * <p> 914 * Valid IPv6 organization-local multicast addresses are FFx8:/112 where x 915 * is a set of flags, and the additional 112 bits make up the 916 * organization-local multicast address space. 917 * </p> 918 * <p> 919 * Valid IPv4 organization-local addresses are between: 239.192.0.0 to 920 * 239.251.255.255 921 * </p> 922 * 923 * @return {@code true} if this instance represents a organization-local 924 * multicast address, {@code false} otherwise. 925 * @since Android 1.0 926 */ 927 public boolean isMCOrgLocal() { 928 return false; 929 } 930 931 /** 932 * Returns whether this is a wildcard address or not. This implementation 933 * returns always {@code false}. 934 * 935 * @return {@code true} if this instance represents a wildcard address, 936 * {@code false} otherwise. 937 * @since Android 1.0 938 */ 939 public boolean isAnyLocalAddress() { 940 return false; 941 } 942 943 /** 944 * Tries to reach this {@code InetAddress}. This method first tries to use 945 * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection 946 * on port 7 (Echo) of the remote host is established. 947 * 948 * @param timeout 949 * timeout in milliseconds before the test fails if no connection 950 * could be established. 951 * @return {@code true} if this address is reachable, {@code false} 952 * otherwise. 953 * @throws IOException 954 * if an error occurs during an I/O operation. 955 * @throws IllegalArgumentException 956 * if timeout is less than zero. 957 * @since Android 1.0 958 */ 959 public boolean isReachable(int timeout) throws IOException { 960 return isReachable(null, 0, timeout); 961 } 962 963 /** 964 * Tries to reach this {@code InetAddress}. This method first tries to use 965 * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection 966 * on port 7 (Echo) of the remote host is established. 967 * 968 * @param netif 969 * the network interface on which to connection should be 970 * established. 971 * @param ttl 972 * the maximum count of hops (time-to-live). 973 * @param timeout 974 * timeout in milliseconds before the test fails if no connection 975 * could be established. 976 * @return {@code true} if this address is reachable, {@code false} 977 * otherwise. 978 * @throws IOException 979 * if an error occurs during an I/O operation. 980 * @throws IllegalArgumentException 981 * if ttl or timeout is less than zero. 982 * @since Android 1.0 983 */ 984 public boolean isReachable(NetworkInterface netif, final int ttl, 985 final int timeout) throws IOException { 986 if (0 > ttl || 0 > timeout) { 987 throw new IllegalArgumentException(Msg.getString("K0051")); //$NON-NLS-1$ 988 } 989 boolean reachable = false; 990 if (null == netif) { 991 // network interface is null, binds to no address 992 // BEGIN android-changed 993 // reachable = NETIMPL.isReachableByICMP(this, null, ttl, timeout); 994 // if (!reachable) { 995 reachable = isReachableByTCP(this, null, timeout); 996 // } 997 // END android-changed 998 } else { 999 // Not Bind to any address 1000 if (null == netif.addresses) { 1001 return false; 1002 } 1003 // binds to all address on this NetworkInterface, tries ICMP ping 1004 // first 1005 // BEGIN android-changed 1006 // reachable = isReachableByICMPUseMultiThread(netif, ttl, timeout); 1007 // if (!reachable) { 1008 // tries TCP echo if ICMP ping fails 1009 reachable = isReachableByMultiThread(netif, ttl, timeout); 1010 // } 1011 // END adnroid-changed 1012 } 1013 return reachable; 1014 } 1015 1016 /* 1017 * Uses multi-Thread to try if isReachable, returns true if any of threads 1018 * returns in time 1019 */ 1020 // BEGIN android-changed 1021 private boolean isReachableByMultiThread(NetworkInterface netif, 1022 final int ttl, final int timeout) 1023 // END android-changed 1024 throws IOException { 1025 if (null == netif.addresses) { 1026 return false; 1027 } 1028 Enumeration<InetAddress> addresses = netif.getInetAddresses(); 1029 reached = false; 1030 addrCount = netif.addresses.length; 1031 boolean needWait = false; 1032 while (addresses.hasMoreElements()) { 1033 final InetAddress addr = addresses.nextElement(); 1034 1035 // loopback interface can only reach to local addresses 1036 if (addr.isLoopbackAddress()) { 1037 Enumeration<NetworkInterface> NetworkInterfaces = NetworkInterface 1038 .getNetworkInterfaces(); 1039 while (NetworkInterfaces.hasMoreElements()) { 1040 NetworkInterface networkInterface = NetworkInterfaces 1041 .nextElement(); 1042 Enumeration<InetAddress> localAddresses = networkInterface 1043 .getInetAddresses(); 1044 while (localAddresses.hasMoreElements()) { 1045 if (InetAddress.this.equals(localAddresses 1046 .nextElement())) { 1047 return true; 1048 } 1049 } 1050 } 1051 1052 synchronized (waitReachable) { 1053 addrCount--; 1054 1055 if (addrCount == 0) { 1056 // if count equals zero, all thread 1057 // expired,notifies main thread 1058 waitReachable.notifyAll(); 1059 } 1060 } 1061 continue; 1062 } 1063 1064 needWait = true; 1065 new Thread() { 1066 @Override 1067 public void run() { 1068 boolean threadReached = false; 1069 // BEGIN android-changed 1070 // if isICMP, tries ICMP ping, else TCP echo 1071 // if (isICMP) { 1072 // threadReached = NETIMPL.isReachableByICMP( 1073 // InetAddress.this, addr, ttl, timeout); 1074 // } else { 1075 try { 1076 threadReached = isReachableByTCP(InetAddress.this, 1077 addr, timeout); 1078 } catch (IOException e) { 1079 // do nothing 1080 } 1081 // } 1082 // END android-changed 1083 1084 synchronized (waitReachable) { 1085 if (threadReached) { 1086 // if thread reached this address, sets reached to 1087 // true and notifies main thread 1088 reached = true; 1089 waitReachable.notifyAll(); 1090 } else { 1091 addrCount--; 1092 if (0 == addrCount) { 1093 // if count equals zero, all thread 1094 // expired,notifies main thread 1095 waitReachable.notifyAll(); 1096 } 1097 } 1098 } 1099 } 1100 }.start(); 1101 } 1102 1103 if (needWait) { 1104 synchronized (waitReachable) { 1105 try { 1106 while (!reached && (addrCount != 0)) { 1107 // wait for notification 1108 waitReachable.wait(1000); 1109 } 1110 } catch (InterruptedException e) { 1111 // do nothing 1112 } 1113 return reached; 1114 } 1115 } 1116 1117 return false; 1118 } 1119 1120 // BEGIN android-removed 1121 // private boolean isReachableByICMPUseMultiThread(NetworkInterface netif, 1122 // int ttl, int timeout) throws IOException { 1123 // return isReachableByMultiThread(netif, ttl, timeout, true); 1124 // } 1125 // 1126 // private boolean isReachableByTCPUseMultiThread(NetworkInterface netif, 1127 // int ttl, int timeout) throws IOException { 1128 // return isReachableByMultiThread(netif, ttl, timeout, false); 1129 // } 1130 // END android-removed 1131 1132 private boolean isReachableByTCP(InetAddress dest, InetAddress source, 1133 int timeout) throws IOException { 1134 FileDescriptor fd = new FileDescriptor(); 1135 // define traffic only for parameter 1136 int traffic = 0; 1137 boolean reached = false; 1138 NETIMPL.createSocket(fd, NetUtil.preferIPv4Stack()); 1139 try { 1140 if (null != source) { 1141 NETIMPL.bind(fd, 0, source); 1142 } 1143 NETIMPL.connectStreamWithTimeoutSocket(fd, 7, timeout, traffic, 1144 dest); 1145 reached = true; 1146 } catch (IOException e) { 1147 if (ERRMSG_CONNECTION_REFUSED.equals(e.getMessage())) { 1148 // Connection refused means the IP is reachable 1149 reached = true; 1150 } 1151 } 1152 1153 NETIMPL.socketClose(fd); 1154 1155 return reached; 1156 } 1157 1158 /** 1159 * Returns the {@code InetAddress} corresponding to the array of bytes. In 1160 * the case of an IPv4 address there must be exactly 4 bytes and for IPv6 1161 * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. 1162 * <p> 1163 * The IP address is not validated by a name service. 1164 * </p> 1165 * <p> 1166 * The high order byte is {@code ipAddress[0]}. 1167 * </p> 1168 * 1169 * @param ipAddress 1170 * is either a 4 (IPv4) or 16 (IPv6) byte long array. 1171 * @return an {@code InetAddress} instance representing the given IP address 1172 * {@code ipAddress}. 1173 * @throws UnknownHostException 1174 * if the given byte array has no valid length. 1175 * @since Android 1.0 1176 */ 1177 public static InetAddress getByAddress(byte[] ipAddress) 1178 throws UnknownHostException { 1179 // simply call the method by the same name specifying the default scope 1180 // id of 0 1181 return getByAddress(ipAddress, 0); 1182 } 1183 1184 /** 1185 * Returns the {@code InetAddress} corresponding to the array of bytes. In 1186 * the case of an IPv4 address there must be exactly 4 bytes and for IPv6 1187 * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. The 1188 * IP address is not validated by a name service. The high order byte is 1189 * {@code ipAddress[0]}. 1190 * 1191 * @param ipAddress 1192 * either a 4 (IPv4) or 16 (IPv6) byte array. 1193 * @param scope_id 1194 * the scope id for an IPV6 scoped address. If not a scoped 1195 * address just pass in 0. 1196 * @return the InetAddress 1197 * @throws UnknownHostException 1198 */ 1199 static InetAddress getByAddress(byte[] ipAddress, int scope_id) 1200 throws UnknownHostException { 1201 byte[] copy_address; 1202 if (ipAddress != null && ipAddress.length == 4) { 1203 copy_address = new byte[4]; 1204 for (int i = 0; i < 4; i++) { 1205 copy_address[i] = ipAddress[i]; 1206 } 1207 // BEGIN adnroid-changed 1208 // Copied from a newer version of harmony 1209 return new Inet4Address(copy_address); 1210 // END android-changed 1211 } 1212 1213 if (ipAddress != null && ipAddress.length == 16) { 1214 // First check to see if the address is an IPv6-mapped 1215 // IPv4 address. If it is, then we can make it a IPv4 1216 // address, otherwise, we'll create an IPv6 address. 1217 if (isIPv4MappedAddress(ipAddress)) { 1218 copy_address = new byte[4]; 1219 for (int i = 0; i < 4; i++) { 1220 copy_address[i] = ipAddress[12 + i]; 1221 } 1222 return new Inet4Address(copy_address); 1223 } 1224 copy_address = ipAddress.clone(); 1225 return new Inet6Address(copy_address, scope_id); 1226 } 1227 throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$ 1228 } 1229 1230 private static boolean isIPv4MappedAddress(byte ipAddress[]) { 1231 // Check if the address matches ::FFFF:d.d.d.d 1232 // The first 10 bytes are 0. The next to are -1 (FF). 1233 // The last 4 bytes are varied. 1234 for (int i = 0; i < 10; i++) { 1235 if (ipAddress[i] != 0) { 1236 return false; 1237 } 1238 } 1239 1240 if (ipAddress[10] != -1 || ipAddress[11] != -1) { 1241 return false; 1242 } 1243 1244 return true; 1245 } 1246 1247 /** 1248 * Returns the {@code InetAddress} corresponding to the array of bytes, and 1249 * the given hostname. In the case of an IPv4 address there must be exactly 1250 * 4 bytes and for IPv6 exactly 16 bytes. If not, an {@code 1251 * UnknownHostException} will be thrown. 1252 * <p> 1253 * The host name and IP address are not validated. 1254 * </p> 1255 * <p> 1256 * The hostname either be a machine alias or a valid IPv6 or IPv4 address 1257 * format. 1258 * </p> 1259 * <p> 1260 * The high order byte is {@code ipAddress[0]}. 1261 * </p> 1262 * 1263 * @param hostName 1264 * the string representation of hostname or IP address. 1265 * @param ipAddress 1266 * either a 4 (IPv4) or 16 (IPv6) byte long array. 1267 * @return an {@code InetAddress} instance representing the given IP address 1268 * and hostname. 1269 * @throws UnknownHostException 1270 * if the given byte array has no valid length. 1271 * @since Android 1.0 1272 */ 1273 public static InetAddress getByAddress(String hostName, byte[] ipAddress) 1274 throws UnknownHostException { 1275 // just call the method by the same name passing in a default scope id 1276 // of 0 1277 return getByAddressInternal(hostName, ipAddress, 0); 1278 } 1279 1280 /** 1281 * Returns the {@code InetAddress} corresponding to the array of bytes, and 1282 * the given hostname. In the case of an IPv4 address there must be exactly 1283 * 4 bytes and for IPv6 exactly 16 bytes. If not, an {@code 1284 * UnknownHostException} is thrown. The host name and IP address are not 1285 * validated. The hostname either be a machine alias or a valid IPv6 or IPv4 1286 * address format. The high order byte is {@code ipAddress[0]}. 1287 * 1288 * @param hostName 1289 * string representation of hostname or IP address. 1290 * @param ipAddress 1291 * either a 4 (IPv4) or 16 (IPv6) byte array. 1292 * @param scope_id 1293 * the scope id for a scoped address. If not a scoped address 1294 * just pass in 0. 1295 * @return the InetAddress 1296 * @throws UnknownHostException 1297 */ 1298 static InetAddress getByAddressInternal(String hostName, byte[] ipAddress, 1299 int scope_id) throws UnknownHostException { 1300 byte[] copy_address; 1301 if (ipAddress != null && ipAddress.length == 4) { 1302 copy_address = new byte[4]; 1303 for (int i = 0; i < 4; i++) { 1304 copy_address[i] = ipAddress[i]; 1305 } 1306 return new Inet4Address(ipAddress, hostName); 1307 } 1308 1309 if (ipAddress != null && ipAddress.length == 16) { 1310 // First check to see if the address is an IPv6-mapped 1311 // IPv4 address. If it is, then we can make it a IPv4 1312 // address, otherwise, we'll create an IPv6 address. 1313 if (isIPv4MappedAddress(ipAddress)) { 1314 copy_address = new byte[4]; 1315 for (int i = 0; i < 4; i++) { 1316 copy_address[i] = ipAddress[12 + i]; 1317 } 1318 return new Inet4Address(ipAddress, hostName); 1319 } 1320 1321 copy_address = new byte[16]; 1322 for (int i = 0; i < 16; i++) { 1323 copy_address[i] = ipAddress[i]; 1324 } 1325 1326 return new Inet6Address(ipAddress, hostName, scope_id); 1327 } 1328 1329 throw new UnknownHostException(Msg.getString("K0332", hostName)); //$NON-NLS-1$ 1330 } 1331 1332 /** 1333 * Takes the integer and chops it into 4 bytes, putting it into the byte 1334 * array starting with the high order byte at the index start. This method 1335 * makes no checks on the validity of the parameters. 1336 */ 1337 static void intToBytes(int value, byte bytes[], int start) { 1338 // Shift the int so the current byte is right-most 1339 // Use a byte mask of 255 to single out the last byte. 1340 bytes[start] = (byte) ((value >> 24) & 255); 1341 bytes[start + 1] = (byte) ((value >> 16) & 255); 1342 bytes[start + 2] = (byte) ((value >> 8) & 255); 1343 bytes[start + 3] = (byte) (value & 255); 1344 } 1345 1346 /** 1347 * Takes the byte array and creates an integer out of four bytes starting at 1348 * start as the high-order byte. This method makes no checks on the validity 1349 * of the parameters. 1350 */ 1351 static int bytesToInt(byte bytes[], int start) { 1352 // First mask the byte with 255, as when a negative 1353 // signed byte converts to an integer, it has bits 1354 // on in the first 3 bytes, we are only concerned 1355 // about the right-most 8 bits. 1356 // Then shift the rightmost byte to align with its 1357 // position in the integer. 1358 int value = ((bytes[start + 3] & 255)) 1359 | ((bytes[start + 2] & 255) << 8) 1360 | ((bytes[start + 1] & 255) << 16) 1361 | ((bytes[start] & 255) << 24); 1362 return value; 1363 } 1364 1365 /** 1366 * Creates an InetAddress based on the {@code ipAddressString}. No error 1367 * handling is performed here. 1368 */ 1369 static InetAddress createHostNameFromIPAddress(String ipAddressString) 1370 throws UnknownHostException { 1371 1372 InetAddress address = null; 1373 1374 if (Inet6Util.isValidIPV4Address(ipAddressString)) { 1375 byte[] byteAddress = new byte[4]; 1376 String[] parts = ipAddressString.split("\\."); //$NON-NLS-1$ 1377 int length = parts.length; 1378 if (length == 1) { 1379 long value = Long.parseLong(parts[0]); 1380 for (int i = 0; i < 4; i++) { 1381 byteAddress[i] = (byte) (value >> ((3 - i) * 8)); 1382 } 1383 } else { 1384 for (int i = 0; i < length; i++) { 1385 byteAddress[i] = (byte) Integer.parseInt(parts[i]); 1386 } 1387 } 1388 1389 // adjust for 2/3 parts address 1390 if (length == 2) { 1391 byteAddress[3] = byteAddress[1]; 1392 byteAddress[1] = 0; 1393 } 1394 if (length == 3) { 1395 byteAddress[3] = byteAddress[2]; 1396 byteAddress[2] = 0; 1397 } 1398 1399 address = new Inet4Address(byteAddress); 1400 } else { // otherwise it must be ipv6 1401 1402 if (ipAddressString.charAt(0) == '[') { 1403 ipAddressString = ipAddressString.substring(1, ipAddressString 1404 .length() - 1); 1405 } 1406 1407 StringTokenizer tokenizer = new StringTokenizer(ipAddressString, 1408 ":.%", true); //$NON-NLS-1$ 1409 ArrayList<String> hexStrings = new ArrayList<String>(); 1410 ArrayList<String> decStrings = new ArrayList<String>(); 1411 String scopeString = null; 1412 String token = ""; //$NON-NLS-1$ 1413 String prevToken = ""; //$NON-NLS-1$ 1414 String prevPrevToken = ""; //$NON-NLS-1$ 1415 int doubleColonIndex = -1; // If a double colon exists, we need to 1416 // insert 0s. 1417 1418 // Go through the tokens, including the separators ':' and '.' 1419 // When we hit a : or . the previous token will be added to either 1420 // the hex list or decimal list. In the case where we hit a :: 1421 // we will save the index of the hexStrings so we can add zeros 1422 // in to fill out the string 1423 while (tokenizer.hasMoreTokens()) { 1424 prevPrevToken = prevToken; 1425 prevToken = token; 1426 token = tokenizer.nextToken(); 1427 1428 if (token.equals(":")) { //$NON-NLS-1$ 1429 if (prevToken.equals(":")) { //$NON-NLS-1$ 1430 doubleColonIndex = hexStrings.size(); 1431 } else if (!prevToken.equals("")) { //$NON-NLS-1$ 1432 hexStrings.add(prevToken); 1433 } 1434 } else if (token.equals(".")) { //$NON-NLS-1$ 1435 decStrings.add(prevToken); 1436 } else if (token.equals("%")) { //$NON-NLS-1$ 1437 // add the last word before the % properly 1438 if (!prevToken.equals(":") && !prevToken.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ 1439 if (prevPrevToken.equals(":")) { //$NON-NLS-1$ 1440 hexStrings.add(prevToken); 1441 } else if (prevPrevToken.equals(".")) { //$NON-NLS-1$ 1442 decStrings.add(prevToken); 1443 } 1444 } 1445 1446 // the rest should be the scope string 1447 scopeString = tokenizer.nextToken(); 1448 while (tokenizer.hasMoreTokens()) { 1449 scopeString = scopeString + tokenizer.nextToken(); 1450 } 1451 } 1452 } 1453 1454 if (prevToken.equals(":")) { //$NON-NLS-1$ 1455 if (token.equals(":")) { //$NON-NLS-1$ 1456 doubleColonIndex = hexStrings.size(); 1457 } else { 1458 hexStrings.add(token); 1459 } 1460 } else if (prevToken.equals(".")) { //$NON-NLS-1$ 1461 decStrings.add(token); 1462 } 1463 1464 // figure out how many hexStrings we should have 1465 // also check if it is a IPv4 address 1466 int hexStringsLength = 8; 1467 1468 // If we have an IPv4 address tagged on at the end, subtract 1469 // 4 bytes, or 2 hex words from the total 1470 if (decStrings.size() > 0) { 1471 hexStringsLength -= 2; 1472 } 1473 1474 // if we hit a double Colon add the appropriate hex strings 1475 if (doubleColonIndex != -1) { 1476 int numberToInsert = hexStringsLength - hexStrings.size(); 1477 for (int i = 0; i < numberToInsert; i++) { 1478 hexStrings.add(doubleColonIndex, "0"); //$NON-NLS-1$ 1479 } 1480 } 1481 1482 byte ipByteArray[] = new byte[16]; 1483 1484 // Finally convert these strings to bytes... 1485 for (int i = 0; i < hexStrings.size(); i++) { 1486 Inet6Util.convertToBytes(hexStrings.get(i), ipByteArray, i * 2); 1487 } 1488 1489 // Now if there are any decimal values, we know where they go... 1490 for (int i = 0; i < decStrings.size(); i++) { 1491 ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings 1492 .get(i)) & 255); 1493 } 1494 1495 // now check to see if this guy is actually and IPv4 address 1496 // an ipV4 address is ::FFFF:d.d.d.d 1497 boolean ipV4 = true; 1498 for (int i = 0; i < 10; i++) { 1499 if (ipByteArray[i] != 0) { 1500 ipV4 = false; 1501 break; 1502 } 1503 } 1504 1505 if (ipByteArray[10] != -1 || ipByteArray[11] != -1) { 1506 ipV4 = false; 1507 } 1508 1509 if (ipV4) { 1510 byte ipv4ByteArray[] = new byte[4]; 1511 for (int i = 0; i < 4; i++) { 1512 ipv4ByteArray[i] = ipByteArray[i + 12]; 1513 } 1514 address = InetAddress.getByAddress(ipv4ByteArray); 1515 } else { 1516 int scopeId = 0; 1517 if (scopeString != null) { 1518 try { 1519 scopeId = Integer.parseInt(scopeString); 1520 } catch (Exception e) { 1521 // this should not occur as we should not get into this 1522 // function unless the address is in a valid format 1523 } 1524 } 1525 address = InetAddress.getByAddress(ipByteArray, scopeId); 1526 } 1527 } 1528 1529 return address; 1530 } 1531 1532 static boolean preferIPv6Addresses() { 1533 String result = AccessController.doPrivileged(new PriviAction<String>( 1534 "java.net.preferIPv6Addresses")); //$NON-NLS-1$ 1535 return "true".equals(result); //$NON-NLS-1$ 1536 } 1537 1538 private static final ObjectStreamField[] serialPersistentFields = { 1539 new ObjectStreamField("address", Integer.TYPE), //$NON-NLS-1$ 1540 new ObjectStreamField("family", Integer.TYPE), //$NON-NLS-1$ 1541 new ObjectStreamField("hostName", String.class) }; //$NON-NLS-1$ 1542 1543 private void writeObject(ObjectOutputStream stream) throws IOException { 1544 ObjectOutputStream.PutField fields = stream.putFields(); 1545 if (ipaddress == null) { 1546 fields.put("address", 0); //$NON-NLS-1$ 1547 } else { 1548 fields.put("address", bytesToInt(ipaddress, 0)); //$NON-NLS-1$ 1549 } 1550 fields.put("family", family); //$NON-NLS-1$ 1551 fields.put("hostName", hostName); //$NON-NLS-1$ 1552 1553 stream.writeFields(); 1554 } 1555 1556 private void readObject(ObjectInputStream stream) throws IOException, 1557 ClassNotFoundException { 1558 ObjectInputStream.GetField fields = stream.readFields(); 1559 int addr = fields.get("address", 0); //$NON-NLS-1$ 1560 ipaddress = new byte[4]; 1561 intToBytes(addr, ipaddress, 0); 1562 hostName = (String) fields.get("hostName", null); //$NON-NLS-1$ 1563 family = fields.get("family", 2); //$NON-NLS-1$ 1564 } 1565 1566 private Object readResolve() throws ObjectStreamException { 1567 return new Inet4Address(ipaddress, hostName); 1568 } 1569} 1570