InetAddress.java 22 KB
Newer Older
1
/* InetAddress.java -- Class to model an Internet address
2
   Copyright (C) 1998, 1999, 2002, 2004, 2005  Free Software Foundation, Inc.
Tom Tromey committed
3

4
This file is part of GNU Classpath.
Tom Tromey committed
5

6 7 8 9
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
10

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */
Tom Tromey committed
37

38

Tom Tromey committed
39
package java.net;
40

41
import gnu.classpath.Configuration;
42

43
import java.io.IOException;
44 45
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
46
import java.io.ObjectStreamException;
47
import java.io.Serializable;
48 49 50 51 52 53

/**
 * This class models an Internet address.  It does not have a public
 * constructor.  Instead, new instances of this objects are created
 * using the static methods getLocalHost(), getByName(), and
 * getAllByName().
54 55
 *
 * <p>This class fulfills the function of the C style functions gethostname(),
56
 * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
57
 * into their corresponding numeric addresses and vice versa.</p>
58
 *
59
 * @author Aaron M. Renn (arenn@urbanophile.com)
60
 * @author Per Bothner
61 62
 *
 * @specnote This class is not final since JK 1.4
Tom Tromey committed
63
 */
64
public class InetAddress implements Serializable
Tom Tromey committed
65
{
66
  private static final long serialVersionUID = 3286316764910316507L;
67

68 69 70
  /**
   * Dummy InetAddress, used to bind socket to any (all) network interfaces.
   */
71
  static InetAddress ANY_IF;
72
    
73 74 75
  private static final byte[] loopbackAddress = { 127, 0, 0, 1 };

  private static final InetAddress loopback 
76
    = new Inet4Address(loopbackAddress, "localhost");
77 78 79

  private static InetAddress localhost = null;

80 81 82 83
  static
  {
    // load the shared library needed for name resolution
    if (Configuration.INIT_LOAD_LIBRARY)
84
      System.loadLibrary("javanet");
85 86
    
    byte[] zeros = { 0, 0, 0, 0 };
87
    ANY_IF = new Inet4Address(zeros, "0.0.0.0");
88 89
  }

90 91 92 93 94
  /**
   * The Serialized Form specifies that an int 'address' is saved/restored.
   * This class uses a byte array internally so we'll just do the conversion
   * at serialization time and leave the rest of the algorithm as is.
   */
95
  private int address;
96 97 98 99

  /**
   * An array of octets representing an IP address.
   */
100
  transient byte[] addr;
101 102 103 104

  /**
   * The name of the host for this address.
   */
105
  String hostName;
106

107 108 109 110 111 112 113
  /**
   * The field 'family' seems to be the AF_ value.
   * FIXME: Much of the code in the other java.net classes does not make
   * use of this family field.  A better implementation would be to make
   * use of getaddrinfo() and have other methods just check the family
   * field rather than examining the length of the address each time.
   */
114 115
  int family;

116
  /**
117
   * Initializes this object's addr instance variable from the passed in
118
   * byte array.  Note that this constructor is protected and is called
119 120 121 122 123
   * only by static methods in this class.
   *
   * @param ipaddr The IP number of this address as an array of bytes
   * @param hostname The hostname of this IP address.
   */
124
  InetAddress(byte[] ipaddr, String hostname)
Tom Tromey committed
125
  {
126
    addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
127
    hostName = hostname;
128
    
129 130
    if (ipaddr != null)
      family = getFamily(ipaddr);
Tom Tromey committed
131 132
  }

133
  /**
134 135 136 137 138
   * Returns true if this address is a multicast address, false otherwise.
   * An address is multicast if the high four bits are "1110".  These are
   * also known as "Class D" addresses.
   *
   * @return true if mulitcast, false if not
139 140 141
   *
   * @since 1.1
   */
142
  public boolean isMulticastAddress()
Tom Tromey committed
143
  {
144 145
    // Mask against high order bits of 1110
    if (addr.length == 4)
146
      return (addr[0] & 0xf0) == 0xe0;
147

148
    // Mask against high order bits of 11111111
Michael Koch committed
149
    if (addr.length == 16)
150
      return addr [0] == (byte) 0xFF;
151
    
Tom Tromey committed
152 153 154
    return false;
  }

155 156
  /**
   * Utility routine to check if the InetAddress in a wildcard address
157
   *
158 159
   * @since 1.4
   */
160
  public boolean isAnyLocalAddress()
161
  {
162 163
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
164
    return equals(ANY_IF);
165 166 167 168
  }

  /**
   * Utility routine to check if the InetAddress is a loopback address
169
   *
170 171
   * @since 1.4
   */
172
  public boolean isLoopbackAddress()
173
  {
174 175
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
176
    return (addr[0] & 0xff) == 0x7f;
177 178 179
  }

  /**
180
   * Utility routine to check if InetAddress is a link local address
181
   *
182 183
   * @since 1.4
   */
184
  public boolean isLinkLocalAddress()
185
  {
186 187 188
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
    // XXX: This seems to not exist with IPv4 addresses
189 190 191 192
    return false;
  }

  /**
193
   * Utility routine to check if InetAddress is a site local address
194
   *
195 196
   * @since 1.4
   */
197
  public boolean isSiteLocalAddress()
198
  {
199 200
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
201

202
    // 10.0.0.0/8
203
    if ((addr[0] & 0xff) == 0x0a)
204 205 206
      return true;

    // 172.16.0.0/12
207
    if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
208 209 210
      return true;

    // 192.168.0.0/16
211
    if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
212 213 214
      return true;

    // XXX: Do we need to check more addresses here ?
215 216 217 218
    return false;
  }

  /**
219
   * Utility routine to check if InetAddress is a global multicast address
220
   *
221 222
   * @since 1.4
   */
223
  public boolean isMCGlobal()
224
  {
225 226 227
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
    // XXX: This seems to not exist with IPv4 addresses
228 229 230 231
    return false;
  }

  /**
232
   * Utility routine to check if InetAddress is a node local multicast address.
233
   *
234 235
   * @since 1.4
   */
236
  public boolean isMCNodeLocal()
237
  {
238 239 240
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
    // XXX: This seems to not exist with IPv4 addresses
241 242 243 244
    return false;
  }

  /**
245
   * Utility routine to check if InetAddress is a link local multicast address.
246
   *
247 248
   * @since 1.4
   */
249
  public boolean isMCLinkLocal()
250
  {
251 252
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
253
    if (! isMulticastAddress())
254 255
      return false;

256 257 258
    return ((addr[0] & 0xff) == 0xe0
	    && (addr[1] & 0xff)  == 0x00
	    && (addr[2] & 0xff)  == 0x00);
259 260 261
  }

  /**
262
   * Utility routine to check if InetAddress is a site local multicast address.
263
   *
264 265
   * @since 1.4
   */
266
  public boolean isMCSiteLocal()
267
  {
268 269 270
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
    // XXX: This seems to not exist with IPv4 addresses
271 272 273 274
    return false;
  }

  /**
275 276
   * Utility routine to check if InetAddress is a organization local
   * multicast address.
277
   *
278 279
   * @since 1.4
   */
280
  public boolean isMCOrgLocal()
281
  {
282 283 284
    // This is the IPv4 implementation.
    // Any class derived from InetAddress should override this.
    // XXX: This seems to not exist with IPv4 addresses
285 286 287
    return false;
  }

288
  /**
289 290 291 292
   * Returns the hostname for this address.  This will return the IP address
   * as a String if there is no hostname available for this address
   *
   * @return The hostname for this address
293
   */
294
  public String getHostName()
Tom Tromey committed
295
  {
296 297
    if (hostName != null)
      return hostName;
298

299 300 301
    // Lookup hostname and set field.
    lookup (null, this, false);
    
302
    return hostName;
Tom Tromey committed
303 304
  }

305
  /**
306 307
   * Returns the canonical hostname represented by this InetAddress
   * 
308 309
   * @since 1.4
   */
310
  public String getCanonicalHostName()
311
  {
312
    SecurityManager sm = System.getSecurityManager();
313 314 315 316
    if (sm != null)
      {
        try
	  {
317
            sm.checkConnect(hostName, -1);
318 319 320
	  }
	catch (SecurityException e)
	  {
321
	    return getHostAddress();
322 323 324 325
	  }
      }

    // Try to find the FDQN now
326 327 328 329 330 331 332 333
    InetAddress address;
    byte[] ipaddr = getAddress();

    if (ipaddr.length == 16)
      address = new Inet6Address(getAddress(), null);
    else
      address = new Inet4Address(getAddress(), null);

334
    return address.getHostName();
335 336
  }

337
  /**
338 339 340
   * Returns the IP address of this object as a byte array.
   *
   * @return IP address
341
   */
342
  public byte[] getAddress()
Tom Tromey committed
343 344 345
  {
    // An experiment shows that JDK1.2 returns a different byte array each
    // time.  This makes sense, in terms of security.
346
    return (byte[]) addr.clone();
Tom Tromey committed
347 348 349 350 351
  }

  /* Helper function due to a CNI limitation.  */
  private static InetAddress[] allocArray (int count)
  {
352
    return new InetAddress [count];
Tom Tromey committed
353 354 355 356 357
  }

  /* Helper function due to a CNI limitation.  */
  private static SecurityException checkConnect (String hostname)
  {
358
    SecurityManager s = System.getSecurityManager();
359
    
Tom Tromey committed
360 361
    if (s == null)
      return null;
362
    
Tom Tromey committed
363 364
    try
      {
365
	s.checkConnect (hostname, -1);
Tom Tromey committed
366 367 368 369 370 371 372 373
	return null;
      }
    catch (SecurityException ex)
      {
	return ex;
      }
  }

374
  /**
375
   * Returns the IP address of this object as a String.  The address is in
376 377 378
   * the dotted octet notation, for example, "127.0.0.1".
   *
   * @return The IP address of this object in String form
379 380 381
   *
   * @since 1.0.2
   */
382
  public String getHostAddress()
Tom Tromey committed
383
  {
384 385
    StringBuffer sb = new StringBuffer(40);

386
    int len = addr.length;
Tom Tromey committed
387
    int i = 0;
388
    
Tom Tromey committed
389 390
    if (len == 16)
      { // An IPv6 address.
391
	for ( ; ; i += 2)
Tom Tromey committed
392 393
	  {
	    if (i >= 16)
394 395
	      return sb.toString();
	    
396
	    int x = ((addr [i] & 0xFF) << 8) | (addr [i + 1] & 0xFF);
397 398
	    boolean empty = sb.length() == 0;
	    
Tom Tromey committed
399 400 401 402
	    if (empty)
	      {
		if (i == 10 && x == 0xFFFF)
		  { // IPv4-mapped IPv6 address.
403
		    sb.append (":FFFF:");
Tom Tromey committed
404 405 406 407
		    break;  // Continue as IPv4 address;
		  }
		else if (i == 12)
		  { // IPv4-compatible IPv6 address.
408
		    sb.append (':');
Tom Tromey committed
409 410 411
		    break;  // Continue as IPv4 address.
		  }
		else if (i > 0)
412
		  sb.append ("::");
Tom Tromey committed
413 414
	      }
	    else
415 416
	      sb.append (':');
	    
Tom Tromey committed
417
	    if (x != 0 || i >= 14)
418
	      sb.append (Integer.toHexString (x).toUpperCase());
Tom Tromey committed
419 420
	  }
      }
421 422
    
    for ( ; ; )
Tom Tromey committed
423
      {
424 425
        sb.append(addr[i] & 0xff);
        i++;
426
	
427 428
        if (i == len)
          break;
429
	
430
        sb.append('.');
Tom Tromey committed
431
      }
432

433
    return sb.toString();
Tom Tromey committed
434 435
  }

436
  /**
437 438 439 440
   * Returns a hash value for this address.  Useful for creating hash
   * tables.  Overrides Object.hashCode()
   *
   * @return A hash value for this address.
441
   */
442
  public int hashCode()
Tom Tromey committed
443 444 445 446
  {
    // There hashing algorithm is not specified, but a simple experiment
    // shows that it is equal to the address, as a 32-bit big-endian integer.
    int hash = 0;
447
    int len = addr.length;
Tom Tromey committed
448
    int i = len > 4 ? len - 4 : 0;
449 450

    for (; i < len; i++)
451
      hash = (hash << 8) | (addr[i] & 0xff);
452

Tom Tromey committed
453 454 455
    return hash;
  }

456
  /**
457 458 459 460 461 462 463 464
   * Tests this address for equality against another InetAddress.  The two
   * addresses are considered equal if they contain the exact same octets.
   * This implementation overrides Object.equals()
   *
   * @param obj The address to test for equality
   *
   * @return true if the passed in object's address is equal to this one's,
   * false otherwise
465
   */
466
  public boolean equals(Object obj)
Tom Tromey committed
467
  {
468
    if (! (obj instanceof InetAddress))
Tom Tromey committed
469
      return false;
470

Tom Tromey committed
471 472 473 474
    // "The Java Class Libraries" 2nd edition says "If a machine has
    // multiple names instances of InetAddress for different name of
    // that same machine are not equal.  This is because they have
    // different host names."  This violates the description in the
475
    // JDK 1.2 API documentation.  A little experimentation
Tom Tromey committed
476
    // shows that the latter is correct.
477
    byte[] addr2 = ((InetAddress) obj).addr;
478

479
    if (addr.length != addr2.length)
Tom Tromey committed
480
      return false;
481

482
    for (int i = 0; i < addr.length; i++)
483
      if (addr[i] != addr2[i])
Tom Tromey committed
484
	return false;
485

Tom Tromey committed
486 487 488
    return true;
  }

489
  /**
490 491 492 493 494
   * Converts this address to a String.  This string contains the IP in
   * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
   * to getHostAddress() and overrides Object.toString()
   *
   * @return This address in String form
495
   */
496
  public String toString()
Tom Tromey committed
497
  {
498
    String addr = getHostAddress();
499
    String host = (hostName != null) ? hostName : "";
500
    return host + "/" + addr;
Tom Tromey committed
501
  }
502

503 504 505 506 507 508
  /**
   * Returns an InetAddress object given the raw IP address.
   *
   * The argument is in network byte order: the highest order byte of the
   * address is in getAddress()[0].
   *
509 510
   * @param addr The IP address to create the InetAddress object from
   *
511
   * @exception UnknownHostException If IP address has illegal length
512 513 514
   *
   * @since 1.4
   */
515
  public static InetAddress getByAddress(byte[] addr)
516 517
    throws UnknownHostException
  {
518
    return getByAddress(null, addr);
519
  }
520

521
  /**
522
   * Creates an InetAddress based on the provided host name and IP address.
523 524
   * No name service is checked for the validity of the address.
   *
525 526 527
   * @param host The hostname of the InetAddress object to create
   * @param addr The IP address to create the InetAddress object from
   *
528 529 530 531
   * @exception UnknownHostException If IP address is of illegal length
   *
   * @since 1.4
   */
532
  public static InetAddress getByAddress(String host, byte[] addr)
533 534
    throws UnknownHostException
  {
535
    if (addr.length == 4)
536
      return new Inet4Address(addr, host);
537 538

    if (addr.length == 16)
539 540 541
      return new Inet6Address(addr, host);

    throw new UnknownHostException("IP address has illegal length");
542
  }
543

544
  /**
545
   * If hostname is a valid numeric IP address, return the numeric address.
546
   * Otherwise, return null.
547 548
   *
   * @param hostname the name of the host
549
   */
550
  private static native byte[] aton(String hostname);
Tom Tromey committed
551

552 553 554 555
  /**
   * Looks up all addresses of a given host.
   *
   * @param hostname the host to lookup
556 557
   * @param ipaddr the IP address to lookup
   * @param all return all known addresses for one host
558 559 560
   *
   * @return an array with all found addresses
   */
561
  private static native InetAddress[] lookup (String hostname,
562
		                              InetAddress ipaddr, boolean all);
Tom Tromey committed
563

564 565 566 567 568 569 570 571
  /**
   * Returns tha family type of an IP address.
   *
   * @param addr the IP address
   *
   * @return the family
   */
  private static native int getFamily (byte[] ipaddr);
572

573
  /**
574 575 576
   * Returns an InetAddress object representing the IP address of the given
   * hostname.  This name can be either a hostname such as "www.urbanophile.com"
   * or an IP address in dotted decimal format such as "127.0.0.1".  If the
577
   * hostname is null or "", the hostname of the local machine is supplied by
578 579 580
   * default.  This method is equivalent to returning the first element in
   * the InetAddress array returned from GetAllByName.
   *
581 582
   * @param hostname The name of the desired host, or null for the local 
   * loopback address.
583
   *
584
   * @return The address of the host as an InetAddress object.
585 586 587 588 589 590
   *
   * @exception UnknownHostException If no IP address for the host could
   * be found
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
591
  public static InetAddress getByName(String hostname)
Tom Tromey committed
592 593
    throws UnknownHostException
  {
594 595 596 597 598
    // If null or the empty string is supplied, the loopback address
    // is returned. Note that this is permitted without a security check.
    if (hostname == null || hostname.length() == 0)
      return loopback;

599
    SecurityManager s = System.getSecurityManager();
600
    if (s != null)
601 602
      s.checkConnect(hostname, -1);

603
    // Assume that the host string is an IP address
604
    byte[] address = aton(hostname);
Tom Tromey committed
605
    if (address != null)
606 607 608 609 610
      {
        if (address.length == 4)
          return new Inet4Address (address, null);
        else if (address.length == 16)
          {
611
	    if ((address [10] == 0xFF) && (address [11] == 0xFF))
612
	      {
613 614 615 616 617
		byte[] ip4addr = new byte [4];
		ip4addr [0] = address [12];
		ip4addr [1] = address [13];
		ip4addr [2] = address [14];
		ip4addr [3] = address [15];
618 619 620 621 622 623 624
		return new Inet4Address (ip4addr, null);
	      }
            return new Inet6Address (address, null);
	  }
	else
          throw new UnknownHostException ("Address has invalid length");
      }
625

626
    // Try to resolve the host by DNS
627 628 629
    InetAddress result = new InetAddress(null, null);
    lookup (hostname, result, false);
    return result;
Tom Tromey committed
630 631
  }

632
  /**
633 634 635 636 637 638
   * Returns an array of InetAddress objects representing all the host/ip
   * addresses of a given host, given the host's name.  This name can be
   * either a hostname such as "www.urbanophile.com" or an IP address in
   * dotted decimal format such as "127.0.0.1".  If the value is null, the
   * hostname of the local machine is supplied by default.
   *
639
   * @param hostname The name of the desired host, or null for the
640
   * local loopback address.
641
   *
642
   * @return All addresses of the host as an array of InetAddress objects.
643
   *
644 645 646 647 648
   * @exception UnknownHostException If no IP address for the host could
   * be found
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
649
  public static InetAddress[] getAllByName(String hostname)
Tom Tromey committed
650 651
    throws UnknownHostException
  {
652 653 654 655 656
    // If null or the empty string is supplied, the loopback address
    // is returned. Note that this is permitted without a security check.
    if (hostname == null || hostname.length() == 0)
      return new InetAddress[] {loopback};

657
    SecurityManager s = System.getSecurityManager();
658
    if (s != null)
659
      s.checkConnect(hostname, -1);
660 661 662

    // Check if hostname is an IP address
    byte[] address = aton (hostname);
Tom Tromey committed
663 664
    if (address != null)
      {
665 666
	InetAddress[] result = new InetAddress [1];
	result [0] = new InetAddress (address, null);
Tom Tromey committed
667 668
	return result;
      }
669

670 671
    // Try to resolve the hostname by DNS
    return lookup (hostname, null, true);
Tom Tromey committed
672 673
  }

674 675 676 677 678 679 680 681
  /**
   * This native method looks up the hostname of the local machine
   * we are on.  If the actual hostname cannot be determined, then the
   * value "localhost" will be used.  This native method wrappers the
   * "gethostname" function.
   *
   * @return The local hostname.
   */
682
  private static native String getLocalHostname();
Tom Tromey committed
683

684
  /**
685 686 687 688
   * Returns an InetAddress object representing the address of the current
   * host.
   *
   * @return The local host's address
689 690 691 692
   *
   * @exception UnknownHostException If no IP address for the host could
   * be found
   */
693
  public static InetAddress getLocalHost() throws UnknownHostException
Tom Tromey committed
694
  {
695
    SecurityManager s = System.getSecurityManager();
696
    
Tom Tromey committed
697 698 699 700
    // Experimentation shows that JDK1.2 does cache the result.
    // However, if there is a security manager, and the cached result
    // is other than "localhost", we need to check again.
    if (localhost == null
701
	|| (s != null && ! localhost.isLoopbackAddress()))
702
      getLocalHost (s);
703
    
Tom Tromey committed
704 705 706
    return localhost;
  }

707
  private static synchronized void getLocalHost (SecurityManager s)
Tom Tromey committed
708 709 710 711 712
    throws UnknownHostException
  {
    // Check the localhost cache again, now that we've synchronized.
    if (s == null && localhost != null)
      return;
713
    
714
    String hostname = getLocalHostname();
715
    
Tom Tromey committed
716 717 718 719 720 721 722 723 724 725 726 727
    if (s != null)
      {
	// "The Java Class Libraries" suggests that if the security
	// manager disallows getting the local host name, then
	// we use the loopback host.
	// However, the JDK 1.2 API claims to throw SecurityException,
	// which seems to suggest SecurityException is *not* caught.
	// In this case, experimentation shows that former is correct.
	try
	  {
	    // This is wrong, if the name returned from getLocalHostname()
	    // is not a fully qualified name.  FIXME.
728
	    s.checkConnect (hostname, -1);
Tom Tromey committed
729 730 731 732 733 734
	  }
	catch (SecurityException ex)
	  {
	    hostname = null;
	  }
      }
735
    
736
    if (hostname != null && hostname.length() != 0)
Tom Tromey committed
737 738 739
      {
	try
	  {
740 741
	    localhost = new InetAddress (null, null);
	    lookup (hostname, localhost, false);
Tom Tromey committed
742 743 744 745 746
	  }
	catch (Exception ex)
	  {
	  }
      }
747 748
    else
      throw new UnknownHostException();
749
    
Tom Tromey committed
750
    if (localhost == null)
751
      localhost = new InetAddress (loopbackAddress, "localhost");
Tom Tromey committed
752
  }
753 754 755 756

  /**
   * Needed for serialization
   */
757
  private void readResolve() throws ObjectStreamException
758 759 760
  {
    // FIXME: implement this
  }
761 762

  private void readObject(ObjectInputStream ois)
763 764
    throws IOException, ClassNotFoundException
  {
765
    ois.defaultReadObject();
766 767 768
    addr = new byte[4];
    addr[3] = (byte) address;

769
    for (int i = 2; i >= 0; --i)
770 771
      addr[i] = (byte) (address >>= 8);

772 773 774 775 776 777 778 779
    // Ignore family from serialized data.  Since the saved address is 32 bits
    // the deserialized object will have an IPv4 address i.e. AF_INET family.
    // FIXME: An alternative is to call the aton method on the deserialized
    // hostname to get a new address.  The Serialized Form doc is silent
    // on how these fields are used.
    family = getFamily (addr);
  }

780
  private void writeObject(ObjectOutputStream oos) throws IOException
781 782 783 784 785
  {
    // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
    // or a 16 byte IPv6 address.
    int len = addr.length;
    int i = len - 4;
786

787
    for (; i < len; i++)
788 789
      address = address << 8 | (((int) addr[i]) & 0xFF);

790
    oos.defaultWriteObject();
791
  }
Tom Tromey committed
792
}