/[classpath]/classpath/java/net/InetAddress.java
ViewVC logotype

Contents of /classpath/java/net/InetAddress.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations) (download)
Mon Dec 2 00:28:09 2002 UTC (21 years, 4 months ago) by mark
Branch: MAIN
CVS Tags: classpath-0_05-release
Changes since 1.14: +11 -2 lines
2002-12-01  Mark Wielaard  <mark@klomp.org>

        * native/jni/java-net/java_net_InetAddress.c (getHostByName):
        JCL_ThrowException takes hostname, not host.
        * native/jni/java-net/javanet.c (_javanet_set_remhost_addr): New
        method.
        (_javanet_set_remhost): Use new method.
        (_javanet_connect): Likewise.
        * java/net/InetAddress.java (toString): Include hostname or alias if
        known, but don't lookup.
        * java/net/Socket.java (setSocketImplFactory): Throw SocketException
        when fac == null.

2002-12-01  Julian Dolby  <dolby@us.ibm.com>

        * native/jni/java-net/java_net_PlainSocketImpl.c (available):
        Implement.

1 /* InetAddress.java -- Class to model an Internet address
2 Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.net;
40
41 import java.io.Serializable;
42 import java.util.HashMap;
43 import java.util.StringTokenizer;
44
45 import gnu.classpath.Configuration;
46
47 /**
48 * This class models an Internet address. It does not have a public
49 * constructor. Instead, new instances of this objects are created
50 * using the static methods getLocalHost(), getByName(), and
51 * getAllByName().
52 * <p>
53 * This class fulfills the function of the C style functions gethostname(),
54 * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names
55 * into their corresponding numeric addresses and vice versa.
56 *
57 * @version 0.5
58 *
59 * @author Aaron M. Renn (arenn@urbanophile.com)
60 */
61 public class InetAddress implements Serializable
62 {
63
64 /*************************************************************************/
65
66 /*
67 * Static Variables
68 */
69
70 // Static Initializer to load the shared library needed for name resolution
71 static
72 {
73 if (Configuration.INIT_LOAD_LIBRARY)
74 {
75 System.loadLibrary("javanet");
76 }
77 }
78
79 private static final long serialVersionUID = 3286316764910316507L;
80
81 /**
82 * The default DNS hash table size,
83 * use a prime number happy with hash table
84 */
85 private static final int DEFAULT_CACHE_SIZE = 89;
86
87 /**
88 * The default caching period in minutes
89 */
90 private static final int DEFAULT_CACHE_PERIOD = (4 * 60);
91
92 /**
93 * Percentage of cache entries to purge when the table gets full
94 */
95 private static final int DEFAULT_CACHE_PURGE_PCT = 30;
96
97 /**
98 * The special IP address INADDR_ANY
99 */
100 private static InetAddress inaddr_any;
101
102 /** dummy InetAddress, used to bind socket to any (all) network interfaces */
103 static InetAddress ANY_IF;
104
105 /**
106 * The size of the cache
107 */
108 private static int cache_size = 0;
109
110 /**
111 * The length of time we will continue to read the address from cache
112 * before forcing another lookup
113 */
114 private static int cache_period = 0;
115
116 /**
117 * What percentage of the cache we will purge if it gets full
118 */
119 private static int cache_purge_pct = 0;
120
121 /**
122 * HashMap to use as DNS lookup cachem
123 * use HashMap because all accesses to cache are already synchronized
124 */
125 private static HashMap cache;
126
127 // Static initializer for the cache
128 static
129 {
130 // Look for properties that override default caching behavior
131 cache_size = Integer.getInteger("gnu.java.net.dns_cache_size",
132 DEFAULT_CACHE_SIZE).intValue();
133 cache_period = Integer.getInteger("gnu.java.net.dns_cache_period",
134 DEFAULT_CACHE_PERIOD * 60 * 1000).intValue();
135
136 cache_purge_pct = Integer.getInteger("gnu.java.net.dns_cache_purge_pct",
137 DEFAULT_CACHE_PURGE_PCT).intValue();
138
139 // Fallback to defaults if necessary
140 if ((cache_purge_pct < 1) || (cache_purge_pct > 100))
141 cache_purge_pct = DEFAULT_CACHE_PURGE_PCT;
142
143 // Create the cache
144 if (cache_size != 0)
145 cache = new HashMap (cache_size);
146
147 // precompute the ANY_IF address
148 try
149 {
150 ANY_IF = getInaddrAny();
151 }
152 catch (UnknownHostException uhe)
153 {
154 // Hmmm, make one up and hope that it works.
155 byte[] zeros = {0,0,0,0};
156 ANY_IF = new InetAddress(zeros);
157 }
158 }
159
160 /*************************************************************************/
161
162 /*
163 * Instance variables
164 */
165
166 /**
167 * An array of octets representing an IP address
168 */
169 transient byte[] addr;
170
171 /**
172 * The name of the host for this address
173 */
174 String hostName;
175
176 /**
177 * Backup hostname alias for this address.
178 */
179 transient String hostname_alias;
180
181 /**
182 * The time this address was looked up
183 */
184 transient long lookup_time;
185
186 /**
187 * Required for serialized form
188 */
189 int address;
190 int family;
191
192 /*************************************************************************/
193
194 /*
195 * Class Methods
196 */
197
198 /**
199 * This method checks the DNS cache to see if we have looked this hostname
200 * up before. If so, we return the cached addresses unless it has been in the
201 * cache too long.
202 *
203 * @param hostname The hostname to check for
204 *
205 * @return The InetAddress for this hostname or null if not available
206 */
207 private static synchronized InetAddress[]
208 checkCacheFor(String hostname)
209 {
210 InetAddress[] addresses = null;
211
212 if (cache_size == 0)
213 return(null);
214
215 Object obj = cache.get(hostname);
216 if (obj == null)
217 return(null);
218
219 if (obj instanceof InetAddress[])
220 addresses = (InetAddress[])obj;
221
222 if (addresses == null)
223 return(null);
224
225 if (cache_period != -1)
226 if ((System.currentTimeMillis() - addresses[0].lookup_time) > cache_period)
227 {
228 cache.remove(hostname);
229 return(null);
230 }
231
232 return addresses;
233 }
234
235 /*************************************************************************/
236
237 /**
238 * This method adds an InetAddress object to our DNS cache. Note that
239 * if the cache is full, then we run a purge to get rid of old entries.
240 * This will cause a performance hit, thus applications using lots of
241 * lookups should set the cache size to be very large.
242 *
243 * @param hostname The hostname to cache this address under
244 * @param obj The InetAddress or InetAddress array to store
245 */
246 private static synchronized void
247 addToCache(String hostname, Object obj)
248 {
249 if (cache_size == 0)
250 return;
251
252 // Check to see if hash table is full
253 if (cache_size != -1)
254 if (cache.size() == cache_size)
255 {
256 ; //*** Add code to purge later.
257 }
258
259 cache.put (hostname, obj);
260 }
261
262 /*************************************************************************/
263
264 /**
265 * Returns the special address INADDR_ANY used for binding to a local
266 * port on all IP addresses hosted by a the local host.
267 *
268 * @return An InetAddress object representing INDADDR_ANY
269 *
270 * @exception UnknownHostException If an error occurs
271 */
272 static InetAddress
273 getInaddrAny() throws UnknownHostException
274 {
275 if (inaddr_any == null)
276 {
277 byte[] tmp = lookupInaddrAny();
278 inaddr_any = new InetAddress (tmp);
279 }
280
281 return(inaddr_any);
282 }
283
284 /*************************************************************************/
285
286 /**
287 * Returns an array of InetAddress objects representing all the host/ip
288 * addresses of a given host, given the host's name. This name can be
289 * either a hostname such as "www.urbanophile.com" or an IP address in
290 * dotted decimal format such as "127.0.0.1". If the value is null, the
291 * hostname of the local machine is supplied by default.
292 *
293 * @param hostname The name of the desired host, or null for the local machine
294 *
295 * @return All addresses of the host as an array of InetAddress's
296 *
297 * @exception UnknownHostException If no IP address can be found for the given hostname
298 */
299 public static InetAddress[]
300 getAllByName(String hostname) throws UnknownHostException
301 {
302 // Default to current host if necessary
303 if (hostname == null)
304 {
305 InetAddress local = getLocalHost ();
306 return getAllByName (local.getHostName ());
307 }
308
309 // Check the cache for this host before doing a lookup
310 InetAddress[] addresses = checkCacheFor (hostname);
311 if (addresses != null)
312 return(addresses);
313
314 // Not in cache, try the lookup
315 byte[][] iplist = getHostByName(hostname);
316 if (iplist.length == 0)
317 throw new UnknownHostException(hostname);
318
319 addresses = new InetAddress [iplist.length];
320
321 for (int i = 0; i < iplist.length; i++)
322 {
323 if (iplist[i].length != 4)
324 throw new UnknownHostException(hostname);
325
326 // Don't store the hostname in order to force resolution of the
327 // canonical names of these ip's when the user asks for the hostname
328 // But do specify the host alias so if the IP returned won't
329 // reverse lookup we don't throw an exception.
330 addresses[i] = new InetAddress (iplist [i], null, hostname);
331 }
332
333 addToCache (hostname, addresses);
334
335 return addresses;
336 }
337
338 /*************************************************************************/
339
340 /**
341 * Returns an InetAddress object representing the IP address of the given
342 * hostname. This name can be either a hostname such as "www.urbanophile.com"
343 * or an IP address in dotted decimal format such as "127.0.0.1". If the
344 * hostname is null, the hostname of the local machine is supplied by
345 * default. This method is equivalent to returning the first element in
346 * the InetAddress array returned from GetAllByName.
347 *
348 * @param hostname The name of the desired host, or null for the local machine
349 *
350 * @return The address of the host as an InetAddress
351 *
352 * @exception UnknownHostException If no IP address can be found for the given hostname
353 */
354 public static InetAddress
355 getByName(String hostname) throws UnknownHostException
356 {
357 // Default to current host if necessary
358 if (hostname == null)
359 return getLocalHost();
360
361 // First, check to see if it is an IP address. If so, then don't
362 // do a DNS lookup.
363 StringTokenizer st = new StringTokenizer(hostname, ".");
364 if (st.countTokens() == 4)
365 {
366 int i;
367 byte[] ip = new byte[4];
368 for (i = 0; i < 4; i++)
369 {
370 try
371 {
372 ip[i] = Byte.parseByte(st.nextToken());
373 if ((ip[i] < 0) || (ip[1] > 255))
374 break;
375 }
376 catch (NumberFormatException e)
377 {
378 break;
379 }
380 }
381 if (i == 4)
382 {
383 return(new InetAddress(ip));
384 }
385 }
386
387 // Wasn't an IP, so try the lookup
388 InetAddress[] addresses = getAllByName (hostname);
389
390 return addresses [0];
391 }
392
393 /*************************************************************************/
394
395 /**
396 * Returns an InetAddress object representing the address of the current
397 * host.
398 *
399 * @return The local host's address
400 *
401 * @exception UnknownHostException If an error occurs
402 */
403 public static InetAddress getLocalHost() throws UnknownHostException
404 {
405 String hostname = getLocalHostName();
406 return getByName (hostname);
407 }
408
409 /*************************************************************************/
410
411 /*
412 * Constructors
413 */
414
415 /**
416 * Initializes this object's addr instance variable from the passed in
417 * int array. Note that this constructor is protected and is called
418 * only by static methods in this class.
419 *
420 * @param ipaddr The IP number of this address as an array of bytes
421 */
422 //private
423 public
424 InetAddress(byte[] ipaddr)
425 {
426 this (ipaddr, null, null);
427 }
428
429 /*************************************************************************/
430
431 /**
432 * Initializes this object's addr instance variable from the passed in
433 * int array. Note that this constructor is protected and is called
434 * only by static methods in this class.
435 *
436 * @param ipaddr The IP number of this address as an array of bytes
437 * @param hostname The hostname of this IP address.
438 */
439 //private
440 public
441 InetAddress(byte[] ipaddr, String hostname)
442 {
443 this (ipaddr, hostname, null);
444 }
445
446 /*************************************************************************/
447
448 /**
449 * Initializes this object's addr instance variable from the passed in
450 * int array. Note that this constructor is protected and is called
451 * only by static methods in this class.
452 *
453 * @param ipaddr The IP number of this address as an array of bytes
454 * @param hostname The hostname of this IP address.
455 * @param hostname_alias A backup hostname to use if hostname is null to prevent reverse lookup failures
456 */
457 //private
458 public
459 InetAddress(byte[] ipaddr, String hostname, String hostname_alias)
460 {
461 addr = new byte [ipaddr.length];
462
463 for (int i = 0; i < ipaddr.length; i++)
464 addr [i] = ipaddr [i];
465
466 this.hostName = hostname;
467 this.hostname_alias = hostname_alias;
468 lookup_time = System.currentTimeMillis();
469
470 family = 2; /* AF_INET */
471 address = addr[3] & 0xff;
472 address |= ((addr[2] << 8) & 0xff00);
473 address |= ((addr[1] << 16) & 0xff0000);
474 address |= ((addr[0] << 24) & 0xff000000);
475
476 }
477
478 /*************************************************************************/
479
480 /**
481 * Instance Methods
482 */
483
484 /**
485 * Tests this address for equality against another InetAddress. The two
486 * addresses are considered equal if they contain the exact same octets.
487 * This implementation overrides Object.equals()
488 *
489 * @param obj The address to test for equality
490 *
491 * @return true if the passed in object's address is equal to this one's,
492 * false otherwise
493 */
494 public boolean
495 equals(Object obj)
496 {
497 if (! (obj instanceof InetAddress))
498 return false;
499
500 byte[] test_ip = ((InetAddress) obj).getAddress();
501
502 if (test_ip.length != addr.length)
503 return(false);
504
505 for (int i = 0; i < addr.length; i++)
506 if (test_ip [i] != (byte) addr [i])
507 return(false);
508
509 return(true);
510 }
511
512 /*************************************************************************/
513
514 /**
515 * Returns the IP address of this object as a int array.
516 *
517 * @return IP address
518 */
519 public byte[]
520 getAddress()
521 {
522 byte[] ipaddr = new byte [addr.length];
523
524 for (int i = 0; i < addr.length; i++)
525 {
526 ipaddr [i] = (byte) addr [i];
527 }
528
529 return ipaddr;
530 }
531
532 /*************************************************************************/
533
534 /**
535 * Returns the IP address of this object as a String. The address is in
536 * the dotted octet notation, for example, "127.0.0.1".
537 *
538 * @return The IP address of this object in String form
539 */
540 public String
541 getHostAddress()
542 {
543 StringBuffer sb = new StringBuffer();
544
545 for (int i = 0; i < addr.length; i++)
546 {
547 sb.append (addr [i] & 0xff);
548 if (i < (addr.length - 1))
549 sb.append(".");
550 }
551
552 return sb.toString();
553 }
554
555 /*************************************************************************/
556
557 /**
558 * Returns the hostname for this address. This will return the IP address
559 * as a String if there is no hostname available for this address
560 *
561 * @return The hostname for this address
562 */
563 public String
564 getHostName()
565 {
566 if (hostName != null)
567 return(hostName);
568
569 try
570 {
571 hostName = getHostByAddr (addr);
572 return(hostName);
573 }
574 catch (UnknownHostException e)
575 {
576 if (hostname_alias != null)
577 return(hostname_alias);
578 else
579 return(getHostAddress());
580 }
581 }
582
583 /*************************************************************************/
584
585 /**
586 * Returns a hash value for this address. Useful for creating hash
587 * tables. Overrides Object.hashCode()
588 *
589 * @return A hash value for this address.
590 */
591 public int
592 hashCode()
593 {
594 long val1 = 0, val2 = 0;
595
596 // Its obvious here that I have no idea how to generate a good
597 // hash key
598 for (int i = 0; i < addr.length; i++)
599 val1 = val1 + (addr [i] << ((addr.length - i) / 8));
600
601 for (int i = 0; i < addr.length; i++)
602 val2 = val2 + (addr [i] * 10 * i);
603
604 val1 = (val1 >> 1) ^ val2;
605
606 return((int)val1);
607 }
608
609 /*************************************************************************/
610
611 /**
612 * Returns true if this address is a multicast address, false otherwise.
613 * An address is multicast if the high four bits are "1110". These are
614 * also known as "Class D" addresses.
615 *
616 * @return true if mulitcast, false if not
617 */
618 public boolean
619 isMulticastAddress()
620 {
621 if (addr.length == 0)
622 return(false);
623
624 // Mask against high order bits of 1110
625 if ((addr [0] & 0xF0) == 224)
626 return(true);
627
628 return(false);
629 }
630
631 /*************************************************************************/
632
633 /**
634 * Converts this address to a String. This string contains the IP in
635 * dotted decimal form. For example: "127.0.0.1" This method is equivalent
636 * to getHostAddress() and overrides Object.toString()
637 *
638 * @return This address in String form
639 */
640 public String
641 toString()
642 {
643 StringBuffer sb;
644 if (hostName != null)
645 sb = new StringBuffer(hostName).append('/');
646 else if (hostname_alias != null)
647 sb = new StringBuffer(hostname_alias).append('/');
648 else
649 sb = new StringBuffer();
650
651 sb.append(getHostAddress());
652 return(sb.toString());
653 }
654
655 /**
656 * Returns an InetAddress object given the raw IP address.
657 *
658 * The argument is in network byte order: the highest order byte of the
659 * address is in getAddress()[0].
660 *
661 * @param addr The IP address to create the InetAddress object from
662 *
663 * @exception UnknownHostException If IP address has illegal length
664 *
665 * @since 1.4
666 */
667 public static InetAddress getByAddress(byte[] addr)
668 throws UnknownHostException
669 {
670 if (addr.length != 4 && addr.length != 16)
671 throw new UnknownHostException ("IP address has illegal length");
672
673 if (addr.length == 4)
674 return new Inet4Address (addr, null);
675
676 return new Inet6Address (addr, null);
677 }
678
679 /*************************************************************************/
680
681 /*
682 * Native Methods
683 */
684
685 /**
686 * This native method looks up the hostname of the local machine
687 * we are on. If the actual hostname cannot be determined, then the
688 * value "localhost" we be used. This native method wrappers the
689 * "gethostname" function.
690 *
691 * @return The local hostname.
692 */
693 private static native String getLocalHostName();
694
695 /*************************************************************************/
696
697 /**
698 * Returns the value of the special address INADDR_ANY
699 */
700 private static native byte[] lookupInaddrAny() throws UnknownHostException;
701
702 /*************************************************************************/
703
704 /**
705 * This method returns the hostname for a given IP address. It will
706 * throw an UnknownHostException if the hostname cannot be determined.
707 *
708 * @param ip The IP address as a int arrary
709 *
710 * @return The hostname
711 *
712 * @exception UnknownHostException If the reverse lookup fails
713 */
714 private static native String getHostByAddr(byte[] ip) throws UnknownHostException;
715
716 /*************************************************************************/
717
718 /**
719 * Returns a list of all IP addresses for a given hostname. Will throw
720 * an UnknownHostException if the hostname cannot be resolved.
721 */
722 private static native byte[][] getHostByName(String hostname) throws UnknownHostException;
723
724 } // class InetAddress
725
726

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26