source: trunk/src/gcc/libjava/java/net/InetAddress.java@ 2

Last change on this file since 2 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 8.5 KB
Line 
1// INetAddress.java -- An Internet Protocol (IP) address.
2
3/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11package java.net;
12import java.io.ObjectInputStream;
13import java.io.ObjectOutputStream;
14import java.io.IOException;
15
16/**
17 * @author Per Bothner
18 * @date January 6, 1999.
19 */
20
21/*
22 * Written using on-line Java Platform 1.2 API Specification, as well
23 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
24 * (The latter turns out to have some errors ...)
25 * Status: Believed complete and correct.
26 */
27
28public final class InetAddress implements java.io.Serializable
29{
30 // The Serialized Form specifies that an int 'address' is saved/restored.
31 // This class uses a byte array internally so we'll just do the conversion
32 // at serialization time and leave the rest of the algorithm as is.
33 private int address;
34 transient byte[] addr;
35 String hostName;
36 // The field 'family' seems to be the AF_ value.
37 // FIXME: Much of the code in the other java.net classes does not make
38 // use of this family field. A better implementation would be to make
39 // use of getaddrinfo() and have other methods just check the family
40 // field rather than examining the length of the address each time.
41 int family;
42 private static final long serialVersionUID = 3286316764910316507L;
43
44 private void readObject(ObjectInputStream ois)
45 throws IOException, ClassNotFoundException
46 {
47 ois.defaultReadObject();
48 addr = new byte[4];
49 addr[3] = (byte) address;
50 for (int i = 2; i >= 0; --i)
51 addr[i] = (byte) (address >>= 8);
52 // Ignore family from serialized data. Since the saved address is 32 bits
53 // the deserialized object will have an IPv4 address i.e. AF_INET family.
54 // FIXME: An alternative is to call the aton method on the deserialized
55 // hostname to get a new address. The Serialized Form doc is silent
56 // on how these fields are used.
57 family = getFamily (addr);
58 }
59
60 private void writeObject(ObjectOutputStream oos) throws IOException
61 {
62 // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
63 // or a 16 byte IPv6 address.
64 int len = addr.length;
65 int i = len - 4;
66 for (; i < len; i++)
67 address = address << 8 | (((int) addr[i]) & 0xFF);
68 oos.defaultWriteObject();
69 }
70
71 private static native int getFamily (byte[] address);
72
73 InetAddress (byte[] address, String hostname)
74 {
75 addr = address;
76 hostName = hostname;
77 if (address != null)
78 family = getFamily (address);
79 }
80
81 public boolean isMulticastAddress ()
82 {
83 int len = addr.length;
84 if (len == 4)
85 return (addr[0] & 0xF0) == 0xE0;
86 if (len == 16)
87 return addr[0] == (byte) 0xFF;
88 return false;
89 }
90
91 public String getHostName ()
92 {
93 if (hostName == null)
94 lookup (null, this, false);
95 return hostName;
96 }
97
98 public byte[] getAddress ()
99 {
100 // An experiment shows that JDK1.2 returns a different byte array each
101 // time. This makes sense, in terms of security.
102 return (byte[]) addr.clone();
103 }
104
105 /* Helper function due to a CNI limitation. */
106 private static InetAddress[] allocArray (int count)
107 {
108 return new InetAddress[count];
109 }
110
111 /* Helper function due to a CNI limitation. */
112 private static SecurityException checkConnect (String hostname)
113 {
114 SecurityManager s = System.getSecurityManager();
115 if (s == null)
116 return null;
117 try
118 {
119 s.checkConnect(hostname, -1);
120 return null;
121 }
122 catch (SecurityException ex)
123 {
124 return ex;
125 }
126 }
127
128 public String getHostAddress ()
129 {
130 StringBuffer sbuf = new StringBuffer(40);
131 int len = addr.length;
132 int i = 0;
133 if (len == 16)
134 { // An IPv6 address.
135 for (; ; i += 2)
136 {
137 if (i >= 16)
138 return sbuf.toString();
139 int x = ((addr[i] & 0xFF) << 8) | (addr[i+1] & 0xFF);
140 boolean empty = sbuf.length() == 0;
141 if (empty)
142 {
143 if (i == 10 && x == 0xFFFF)
144 { // IPv4-mapped IPv6 address.
145 sbuf.append(":FFFF:");
146 break; // Continue as IPv4 address;
147 }
148 else if (i == 12)
149 { // IPv4-compatible IPv6 address.
150 sbuf.append(':');
151 break; // Continue as IPv4 address.
152 }
153 else if (i > 0)
154 sbuf.append("::");
155 }
156 else
157 sbuf.append(':');
158 if (x != 0 || i >= 14)
159 sbuf.append(Integer.toHexString(x).toUpperCase());
160 }
161 }
162 for ( ; ; )
163 {
164 sbuf.append(addr[i] & 0xFF);
165 i++;
166 if (i == len)
167 break;
168 sbuf.append('.');
169 }
170 return sbuf.toString();
171 }
172
173 public int hashCode()
174 {
175 // There hashing algorithm is not specified, but a simple experiment
176 // shows that it is equal to the address, as a 32-bit big-endian integer.
177 int hash = 0;
178 int len = addr.length;
179 int i = len > 4 ? len - 4 : 0;
180 for ( ; i < len; i++)
181 hash = (hash << 8) | (addr[i] & 0xFF);
182 return hash;
183 }
184
185 public boolean equals (Object obj)
186 {
187 if (obj == null || ! (obj instanceof InetAddress))
188 return false;
189 // "The Java Class Libraries" 2nd edition says "If a machine has
190 // multiple names instances of InetAddress for different name of
191 // that same machine are not equal. This is because they have
192 // different host names." This violates the description in the
193 // JDK 1.2 API documentation. A little experiementation
194 // shows that the latter is correct.
195 byte[] addr1 = addr;
196 byte[] addr2 = ((InetAddress) obj).addr;
197 if (addr1.length != addr2.length)
198 return false;
199 for (int i = addr1.length; --i >= 0; )
200 if (addr1[i] != addr2[i])
201 return false;
202 return true;
203 }
204
205 public String toString()
206 {
207 return getHostName()+'/'+getHostAddress();
208 }
209
210 /** If host is a valid numeric IP address, return the numeric address.
211 * Otherwise, return null. */
212 private static native byte[] aton (String host);
213
214 private static native InetAddress[] lookup
215 (String hostname, InetAddress addr, boolean all);
216
217 public static InetAddress getByName (String host)
218 throws UnknownHostException
219 {
220 if (host == null)
221 return getLocalHost();
222 byte[] address = aton(host);
223 if (address != null)
224 return new InetAddress(address, null);
225 InetAddress iaddr = new InetAddress(null, host);
226 lookup(host, iaddr, false);
227 return iaddr;
228 }
229
230 public static InetAddress[] getAllByName (String host)
231 throws UnknownHostException
232 {
233 byte[] address = aton(host);
234 if (address != null)
235 {
236 InetAddress[] result = new InetAddress[1];
237 result[0] = new InetAddress(address, null);
238 return result;
239 }
240 return lookup(host, null, true);
241 }
242
243 static final byte[] zeros = {0,0,0,0};
244 /* dummy InetAddress, used to bind socket to any (all) network interfaces */
245 static final InetAddress ANY_IF = new InetAddress(zeros, null);
246
247 private static final byte[] localhostAddress = { 127, 0, 0, 1 };
248
249 private static native String getLocalHostname ();
250
251 private static InetAddress localhost = null;
252
253 public static InetAddress getLocalHost() throws UnknownHostException
254 {
255 SecurityManager s = System.getSecurityManager();
256 // Experimentation shows that JDK1.2 does cache the result.
257 // However, if there is a security manager, and the cached result
258 // is other than "localhost", we need to check again.
259 if (localhost == null
260 || (s != null && localhost.addr != localhostAddress))
261 getLocalHost(s);
262 return localhost;
263 }
264
265 private static synchronized void getLocalHost(SecurityManager s)
266 throws UnknownHostException
267 {
268 // Check the localhost cache again, now that we've synchronized.
269 if (s == null && localhost != null)
270 return;
271 String hostname = getLocalHostname();
272 if (s != null)
273 {
274 // "The Java Class Libraries" suggests that if the security
275 // manager disallows getting the local host name, then
276 // we use the loopback host.
277 // However, the JDK 1.2 API claims to throw SecurityException,
278 // which seems to suggest SecurityException is *not* caught.
279 // In this case, experimentation shows that former is correct.
280 try
281 {
282 // This is wrong, if the name returned from getLocalHostname()
283 // is not a fully qualified name. FIXME.
284 s.checkConnect(hostname, -1);
285 }
286 catch (SecurityException ex)
287 {
288 hostname = null;
289 }
290 }
291 if (hostname != null)
292 {
293 try
294 {
295 localhost = new InetAddress(null, null);
296 lookup(hostname, localhost, false);
297 }
298 catch (Exception ex)
299 {
300 }
301 }
302 if (localhost == null)
303 localhost = new InetAddress (localhostAddress, "localhost");
304 }
305}
Note: See TracBrowser for help on using the repository browser.