8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.net.Inet4Address;
29 import java.net.Inet6Address;
30 import java.net.InetAddress;
31 import java.net.InetSocketAddress;
32 import java.net.ProtocolFamily;
33 import java.net.SocketException;
34 import java.net.StandardProtocolFamily;
35 import java.net.UnknownHostException;
36 import java.nio.channels.UnsupportedAddressTypeException;
37
38 import jdk.internal.access.JavaNetInetAddressAccess;
39 import jdk.internal.access.SharedSecrets;
40 import jdk.internal.misc.Unsafe;
41 import jdk.internal.util.ArraysSupport;
42
43 /**
44 * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
45 * and struct sockaddr_in6.
46 *
47 * This class is not thread safe.
48 */
49 class NativeSocketAddress {
50 private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();
51 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
52 private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
53
54 private static final int AF_INET = AFINET();
55 private static final int AF_INET6 = AFINET6();
56
57 private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4();
58 private static final int SIZEOF_SOCKADDR6 = sizeofSockAddr6();
59 private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);
60 private static final int SIZEOF_FAMILY = sizeofFamily();
61 private static final int OFFSET_FAMILY = offsetFamily();
62 private static final int OFFSET_SIN4_PORT = offsetSin4Port();
63 private static final int OFFSET_SIN4_ADDR = offsetSin4Addr();
64 private static final int OFFSET_SIN6_PORT = offsetSin6Port();
65 private static final int OFFSET_SIN6_ADDR = offsetSin6Addr();
66 private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId();
67 private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo();
68
69 // SOCKETADDRESS
70 private final long address;
71
72 long address() {
73 return address;
74 }
75
76 NativeSocketAddress() {
77 long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS);
78 UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0);
79 this.address = base;
80 }
81
82 /**
83 * Allocate an array of native socket addresses.
84 */
85 static NativeSocketAddress[] allocate(int count) {
86 NativeSocketAddress[] array = new NativeSocketAddress[count];
87 for (int i = 0; i < count; i++) {
88 try {
89 array[i] = new NativeSocketAddress();
90 } catch (OutOfMemoryError e) {
91 freeAll(array);
92 throw e;
93 }
94 }
95 return array;
96 }
97
98 /**
99 * Free all non-null native socket addresses in the given array.
100 */
101 static void freeAll(NativeSocketAddress[] array) {
102 for (int i = 0; i < array.length; i++) {
103 NativeSocketAddress sa = array[i];
104 if (sa != null) {
105 UNSAFE.freeMemory(sa.address);
106 }
107 }
108 }
109
110 /**
111 * Encodes the given InetSocketAddress into this socket address.
112 * @param protocolFamily protocol family
113 * @param isa the InetSocketAddress to encode
114 * @return the size of the socket address (sizeof sockaddr or sockaddr6)
115 * @throws UnsupportedAddressTypeException if the address type is not supported
116 */
117 int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
118 if (protocolFamily == StandardProtocolFamily.INET) {
119 // struct sockaddr
120 InetAddress ia = isa.getAddress();
121 if (!(ia instanceof Inet4Address))
122 throw new UnsupportedAddressTypeException();
123 putFamily(AF_INET);
124 putAddress(AF_INET, ia);
125 putPort(AF_INET, isa.getPort());
126 return SIZEOF_SOCKADDR4;
127 } else {
128 // struct sockaddr6
129 putFamily(AF_INET6);
130 putAddress(AF_INET6, isa.getAddress());
131 putPort(AF_INET6, isa.getPort());
132 UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0);
133 return SIZEOF_SOCKADDR6;
134 }
135 }
136
137 /**
138 * Return an InetSocketAddress to represent the socket address in this buffer.
139 * @throws SocketException if the socket address is not AF_INET or AF_INET6
140 */
141 InetSocketAddress decode() throws SocketException {
142 int family = family();
143 if (family != AF_INET && family != AF_INET6)
144 throw new SocketException("Socket family not recognized");
145 return new InetSocketAddress(address(family), port(family));
146 }
147
148 /**
149 * Find a mismatch between this and another socket address
150 * @return the byte offset of the first mismatch or -1 if no mismatch
151 */
152 private int mismatch(NativeSocketAddress other) {
153 int i = ArraysSupport.vectorizedMismatch(null,
154 this.address,
155 null,
156 other.address,
157 SIZEOF_SOCKETADDRESS,
158 ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
159 if (i >= 0)
160 return i;
161 i = SIZEOF_SOCKETADDRESS - ~i;
162 for (; i < SIZEOF_SOCKETADDRESS; i++) {
163 if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) {
164 return i;
165 }
166 }
167 return -1;
168 }
169
170 @Override
171 public boolean equals(Object other) {
172 if (other instanceof NativeSocketAddress) {
173 return mismatch((NativeSocketAddress) other) < 0;
174 } else {
175 return false;
176 }
177 }
178
179 @Override
180 public int hashCode() {
181 int h = 0;
182 for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) {
183 h = 31 * h + UNSAFE.getByte(address + offset);
184 }
185 return h;
186 }
187
188 @Override
189 public String toString() {
190 int family = family();
191 if (family == AF_INET || family == AF_INET6) {
192 return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
193 + ", address=" + address(family) + ", port=" + port(family);
194 } else {
195 return "<unknown>";
196 }
197 }
198
199 /**
200 * Return the value of the sa_family field.
201 */
202 private int family() {
203 if (SIZEOF_FAMILY == 1) {
204 return UNSAFE.getByte(address + OFFSET_FAMILY);
205 } else if (SIZEOF_FAMILY == 2) {
206 return UNSAFE.getShort(address + OFFSET_FAMILY);
207 } else {
208 throw new InternalError();
209 }
210 }
211
212 /**
213 * Stores the given family in the sa_family field.
214 */
215 private void putFamily(int family) {
216 if (SIZEOF_FAMILY == 1) {
217 UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family);
218 } else if (SIZEOF_FAMILY == 2) {
219 UNSAFE.putShort(address + OFFSET_FAMILY, (short) family);
220 } else {
221 throw new InternalError();
222 }
223 }
224
225 /**
226 * Return the value of the sin_port or sin6_port field. These fields are
227 * stored in network order.
228 */
229 private int port(int family) {
230 byte b1, b2;
231 if (family == AF_INET) {
232 b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT);
233 b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1);
234 } else {
235 b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT);
236 b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1);
237 }
238 return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2);
239 }
240
241 /**
242 * Stores the given port number in the sin_port or sin6_port field. The
243 * port is stored in network order.
244 */
245 private void putPort(int family, int port) {
246 byte b1 = (byte) ((port >> 8) & 0xff);
247 byte b2 = (byte) ((port >> 0) & 0xff);
248 if (family == AF_INET) {
249 UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1);
250 UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2);
251 } else {
252 UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1);
253 UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2);
254 }
255 }
256
257 /**
258 * Return an InetAddress to represent the value of the address in the
259 * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
260 * created with the sin6_scope_id in the sockaddr_in6 structure.
261 */
262 private InetAddress address(int family) {
263 int len;
264 int offset;
265 int scope_id;
266 if (family == AF_INET) {
267 len = 4;
268 offset = OFFSET_SIN4_ADDR;
269 scope_id = 0;
270 } else {
271 len = 16;
272 offset = OFFSET_SIN6_ADDR;
273 scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID);
274 }
275 byte[] bytes = new byte[len];
276 UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len);
277 try {
278 if (scope_id == 0) {
279 return InetAddress.getByAddress(bytes);
280 } else {
281 return Inet6Address.getByAddress(null, bytes, scope_id);
282 }
283 } catch (UnknownHostException e) {
284 throw new InternalError(e);
285 }
286 }
287
288 /**
289 * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id
290 * fields. For IPv6 addresses, the sin6_addr will be popluated with an
291 * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address.
292 */
293 private void putAddress(int family, InetAddress ia) {
294 if (family == AF_INET) {
295 // IPv4 address
296 putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia);
297 } else {
298 int scope_id;
299 if (ia instanceof Inet4Address) {
300 // IPv4-mapped IPv6 address
301 UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0);
302 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff);
303 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff);
304 putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia);
305 scope_id = 0;
306 } else {
307 // IPv6 address
308 var inet6Address = (Inet6Address) ia;
309 putAddress(address + OFFSET_SIN6_ADDR, inet6Address);
310 scope_id = inet6Address.getScopeId();
311 }
312 UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id);
313 }
314 }
315
316 private static void putAddress(long address, Inet4Address ia) {
317 int ipAddress = JNINA.addressValue(ia);
318 // network order
319 UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF));
320 UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF));
321 UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF));
322 UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF));
323 }
324
325 private static void putAddress(long address, Inet6Address ia) {
326 byte[] bytes = JNINA.addressBytes(ia);
327 UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16);
328 }
329
330 private static native int AFINET();
331 private static native int AFINET6();
332 private static native int sizeofSockAddr4();
333 private static native int sizeofSockAddr6();
334 private static native int sizeofFamily();
335 private static native int offsetFamily();
336 private static native int offsetSin4Port();
337 private static native int offsetSin4Addr();
338 private static native int offsetSin6Port();
339 private static native int offsetSin6Addr();
340 private static native int offsetSin6ScopeId();
341 private static native int offsetSin6FlowInfo();
342
343 static {
344 IOUtil.load();
345 }
346 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.lang.invoke.VarHandle;
29 import java.net.Inet4Address;
30 import java.net.Inet6Address;
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.ProtocolFamily;
34 import java.net.SocketException;
35 import java.net.StandardProtocolFamily;
36 import java.net.UnknownHostException;
37 import java.nio.channels.UnsupportedAddressTypeException;
38 import jdk.incubator.foreign.MemoryAddress;
39 import jdk.incubator.foreign.MemoryHandles;
40 import jdk.incubator.foreign.MemoryLayouts;
41 import jdk.incubator.foreign.MemorySegment;
42 import jdk.internal.access.JavaNetInetAddressAccess;
43 import jdk.internal.access.SharedSecrets;
44 import jdk.internal.misc.Unsafe;
45 import jdk.internal.sys.in6_h;
46 import jdk.internal.sys.in_h;
47
48 /**
49 * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
50 * and struct sockaddr_in6.
51 *
52 * This class is not thread safe.
53 */
54 final class NativeSocketAddress {
55 private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();
56
57 private static final int AF_INET = AFINET();
58 private static final int AF_INET6 = AFINET6();
59
60 final long address() {
61 return address.toRawLongValue();
62 }
63
64 private final MemorySegment segment;
65 private final MemoryAddress address;
66
67 private NativeSocketAddress() {
68 segment = allocateNative(in6_h.Csockaddr_in6.sizeof());
69 segment.fill((byte) 0x00);
70 address = segment.baseAddress();
71 }
72
73 /**
74 * Allocate an array of native socket addresses.
75 */
76 static final NativeSocketAddress[] allocate(int count) {
77 NativeSocketAddress[] array = new NativeSocketAddress[count];
78 for (int i = 0; i < count; i++) {
79 try {
80 array[i] = new NativeSocketAddress();
81 } catch (OutOfMemoryError e) {
82 freeAll(array);
83 throw e;
84 }
85 }
86 return array;
87 }
88
89 /**
90 * Free all non-null native socket addresses in the given array.
91 */
92 static final void freeAll(NativeSocketAddress[] array) {
93 for (int i = 0; i < array.length; i++) {
94 NativeSocketAddress sa = array[i];
95 if (sa != null) {
96 sa.segment.close();
97 }
98 }
99 }
100
101 private static final VarHandle sin_family = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_family$VH(), int.class);
102 private static final VarHandle sin6_family = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_family$VH(), int.class);
103
104 /**
105 * Encodes the given InetSocketAddress into this socket address.
106 * @param protocolFamily protocol family
107 * @param isa the InetSocketAddress to encode
108 * @return the size of the socket address (sizeof sockaddr or sockaddr6)
109 * @throws UnsupportedAddressTypeException if the address type is not supported
110 */
111 final int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
112 if (protocolFamily == StandardProtocolFamily.INET) {
113 // struct sockaddr
114 InetAddress ia = isa.getAddress();
115 if (!(ia instanceof Inet4Address))
116 throw new UnsupportedAddressTypeException();
117 sin_family.set(address, AF_INET);
118 in_h.Csockaddr_in.sin_port$set(address, (short) isa.getPort());
119 in_h.Cin_addr.s_addr$set(in_h.Csockaddr_in.sin_addr$addr(address),
120 JNINA.addressValue((Inet4Address) ia));
121 return (int) in_h.Csockaddr_in.sizeof();
122 } else {
123 // struct sockaddr6
124 sin6_family.set(address, AF_INET6);
125 in6_h.Csockaddr_in6.sin6_port$set(address, (short) isa.getPort());
126 in6_h.Csockaddr_in6.sin6_flowinfo$set(address, 0);
127 in6_h.Csockaddr_in6.sin6_addr$addr(address).segment().copyFrom(addressAsSegment(isa.getAddress()));
128 in6_h.Csockaddr_in6.sin6_scope_id$set(address, scopeidFromAddress(isa.getAddress()));
129 return (int) in6_h.Csockaddr_in6.sizeof();
130 }
131 }
132
133 /**
134 * Return an InetSocketAddress to represent the socket address in this buffer.
135 * @throws SocketException if the socket address is not AF_INET or AF_INET6
136 */
137 final InetSocketAddress decode() throws SocketException {
138 int family = (int) sin_family.get(address);
139 if (family != AF_INET && family != AF_INET6)
140 throw new SocketException("Socket family not recognized");
141 return new InetSocketAddress(address(family), port(family));
142 }
143
144 @Override
145 public boolean equals(Object other) {
146 if (!(other instanceof NativeSocketAddress))
147 return false;
148 NativeSocketAddress that = (NativeSocketAddress) other;
149 return this.segment.mismatch(that.segment) == -1;
150 }
151
152 private static final VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class);
153
154 @Override
155 public int hashCode() {
156 int h = 0;
157 final MemoryAddress addr = segment.baseAddress();
158 for (int i = 0 ; i < segment.byteSize() ; i++) {
159 h = 31 * h + (byte) BYTE_HANDLE.get(addr.addOffset(i));
160 }
161 return h;
162 }
163
164 @Override
165 public String toString() {
166 int family = in_h.Csockaddr_in.sin_family$get(address);
167 if (family == AF_INET || family == AF_INET6) {
168 return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
169 + ", address=" + address(family) + ", port=" + port(family);
170 } else {
171 return "<unknown>";
172 }
173 }
174
175 private static final VarHandle sin_port = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_port$VH(), int.class);
176 private static final VarHandle sin6_port = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_port$VH(), int.class);
177
178 /**
179 * Return the value of the sin_port or sin6_port field. These fields are
180 * stored in network order.
181 */
182 private final int port(int family) {
183 if (family == AF_INET) {
184 return (int) sin_port.get(address);
185 } else {
186 return (int) sin6_port.get(address);
187 }
188 }
189
190 /**
191 * Return an InetAddress to represent the value of the address in the
192 * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
193 * created with the sin6_scope_id in the sockaddr_in6 structure.
194 */
195 private final InetAddress address(int family) {
196 try {
197 if (family == AF_INET) {
198 return InetAddress.getByAddress(intToByteArray(in_h.Cin_addr.s_addr$get(in_h.Csockaddr_in.sin_addr$addr(address))));
199 } else {
200 int scope = in6_h.Csockaddr_in6.sin6_scope_id$get(address);
201 byte[] ba = in6_h.Cin6_addr.__u6_addr$addr(in6_h.Csockaddr_in6.sin6_addr$addr(address)).segment().toByteArray();
202 if (scope == 0) {
203 return InetAddress.getByAddress(ba);
204 } else {
205 return Inet6Address.getByAddress(null, ba, scope);
206 }
207 }
208 } catch (UnknownHostException e) {
209 throw new InternalError("should not reach here", e);
210 }
211 }
212
213 private static final byte[] intToByteArray(int value) {
214 return new byte[] { (byte) (value >>> 24),
215 (byte) (value >>> 16),
216 (byte) (value >>> 8),
217 (byte) value};
218 }
219
220 private static final MemorySegment addressAsSegment(InetAddress ia) {
221 return MemorySegment.ofArray(ipv6AddressBytes(ia));
222 }
223
224 private static final byte[] ipv6AddressBytes(InetAddress ia) {
225 if (ia instanceof Inet4Address) {
226 byte[] ba = new byte[16];
227 ba[10] = (byte) 0xFF;
228 ba[11] = (byte) 0xFF;
229 int ipAddress = JNINA.addressValue((Inet4Address) ia);
230 // network order
231 ba[12] = (byte) ((ipAddress >>> 24) & 0xFF);
232 ba[13] = (byte) ((ipAddress >>> 16) & 0xFF);
233 ba[14] = (byte) ((ipAddress >>> 8) & 0xFF);
234 ba[15] = (byte) (ipAddress & 0xFF);
235 return ba;
236 }
237 return JNINA.addressBytes((Inet6Address) ia);
238 }
239
240 private static final int scopeidFromAddress(InetAddress ia) {
241 if (ia instanceof Inet4Address)
242 return 0;
243 return ((Inet6Address) ia).getScopeId();
244 }
245
246 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
247 private static final MemorySegment allocateNative(long byteSize) {
248 long base = UNSAFE.allocateMemory(byteSize);
249 return MemorySegment.ofNativeRestricted(MemoryAddress.ofLong(base), byteSize, null, () -> UNSAFE.freeMemory(base), null);
250 }
251
252 private static native int AFINET();
253 private static native int AFINET6();
254
255 static {
256 IOUtil.load();
257 }
258 }
|