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