1 /*
2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
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 }
|
1 /*
2 * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
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.MethodHandle;
29 import java.lang.invoke.MethodHandles;
30 import java.lang.invoke.MethodType;
31 import java.lang.invoke.VarHandle;
32 import java.net.Inet4Address;
33 import java.net.Inet6Address;
34 import java.net.InetAddress;
35 import java.net.InetSocketAddress;
36 import java.net.ProtocolFamily;
37 import java.net.SocketException;
38 import java.net.StandardProtocolFamily;
39 import java.net.UnknownHostException;
40 import java.nio.ByteOrder;
41 import java.nio.channels.UnsupportedAddressTypeException;
42 import jdk.incubator.foreign.MemoryAddress;
43 import jdk.incubator.foreign.MemoryHandles;
44 import jdk.incubator.foreign.MemoryLayout;
45 import jdk.incubator.foreign.MemoryLayout.PathElement;
46 import jdk.incubator.foreign.MemoryLayouts;
47 import jdk.incubator.foreign.MemorySegment;
48 import jdk.internal.access.JavaNetInetAddressAccess;
49 import jdk.internal.access.SharedSecrets;
50 import static jdk.incubator.foreign.MemoryLayout.PathElement.*;
51
52 /**
53 * A native socket address that is the union of struct sockaddr, struct sockaddr_in,
54 * and struct sockaddr_in6.
55 *
56 * This class is not thread safe.
57 */
58 class NativeSocketAddress {
59 private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();
60
61 private static final int AF_INET = AFINET();
62 private static final int AF_INET6 = AFINET6();
63
64 private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4();
65 private static final int SIZEOF_SOCKADDR6 = sizeofSockAddr6();
66 private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);
67 private static final int SIZEOF_FAMILY = sizeofFamily();
68 private static final int OFFSET_FAMILY = offsetFamily();
69 private static final int OFFSET_SIN4_PORT = offsetSin4Port();
70 private static final int OFFSET_SIN4_ADDR = offsetSin4Addr();
71 private static final int OFFSET_SIN6_PORT = offsetSin6Port();
72 private static final int OFFSET_SIN6_ADDR = offsetSin6Addr();
73 private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId();
74 private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo();
75
76 private static final ByteOrder NETWORK_BYTE_ORDER = ByteOrder.BIG_ENDIAN;
77 private static final ByteOrder HOST_BYTE_ORDER = ByteOrder.nativeOrder();
78
79 private static final MemoryLayout SOCKADDR;
80
81 private static final int SOCKADDR_IN_SIZE;
82 private static final int SOCKADDR_IN6_SIZE;
83
84 private static final VarHandle SA_FAMILY_HANDLE;
85 private static final VarHandle SIN_PORT_HANDLE;
86 private static final VarHandle SIN_ADDR_HANDLE;
87 private static final VarHandle SIN6_PORT_HANDLE;
88 private static final VarHandle SIN6_FLOWINFO_HANDLE;
89 private static final VarHandle SIN6_ADDR_HANDLE;
90 private static final VarHandle SIN6_SCOPE_HANDLE;
91 private static final VarHandle BYTEWISE_HANDLE;
92
93 // byte/short to/from int adapter handles
94 private static final MethodHandle INT_TO_SHORT;
95 private static final MethodHandle SHORT_TO_UNSIGNED_INT;
96 private static final MethodHandle INT_TO_BYTE;
97 private static final MethodHandle BYTE_TO_UNSIGNED_INT;
98
99 private static final boolean VERIFY = true;
100 private static final boolean DEBUG = true;
101
102 static {
103 try {
104 var lookup = MethodHandles.lookup();
105 BYTE_TO_UNSIGNED_INT = lookup.findStatic(Byte.class, "toUnsignedInt", MethodType.methodType(int.class, byte.class));
106 INT_TO_BYTE = lookup.findStatic(NativeSocketAddress.class, "byteValue", MethodType.methodType(byte.class, int.class));
107 SHORT_TO_UNSIGNED_INT = lookup.findStatic(Short.class, "toUnsignedInt", MethodType.methodType(int.class, short.class));
108 INT_TO_SHORT = lookup.findStatic(NativeSocketAddress.class, "shortValue", MethodType.methodType(short.class, int.class));
109 } catch (Throwable throwable) {
110 throw new AssertionError(throwable);
111 }
112
113 MemoryLayout familyLayout;
114 if (OFFSET_FAMILY == 1 && SIZEOF_FAMILY == 1) {
115 familyLayout = MemoryLayout.ofStruct(MemoryLayout.ofPaddingBits(8), MemoryLayouts.JAVA_BYTE.withName("sa_family"));
116 SA_FAMILY_HANDLE = MemoryHandles.filterValue(
117 familyLayout.varHandle(byte.class, groupElement("sa_family")),
118 INT_TO_BYTE,
119 BYTE_TO_UNSIGNED_INT);
120 } else if (OFFSET_FAMILY == 0 && SIZEOF_FAMILY == 2) {
121 familyLayout = MemoryLayouts.JAVA_SHORT.withName("sa_family");
122 SA_FAMILY_HANDLE = MemoryHandles.filterValue(
123 familyLayout.varHandle(short.class),
124 INT_TO_SHORT,
125 SHORT_TO_UNSIGNED_INT);
126 } else {
127 throw new InternalError("unknown family [offset:%d, size:%d]".formatted(OFFSET_FAMILY, SIZEOF_FAMILY));
128 }
129
130 SOCKADDR = MemoryLayout.ofUnion(
131 MemoryLayout.ofStruct(familyLayout,
132 MemoryLayout.ofValueBits(16, NETWORK_BYTE_ORDER).withName("sin_port"),
133 //MemoryLayouts.BITS_32_BE.withName("sin_addr")) // #### treat as bits rather than bytes?
134 MemoryLayout.ofSequence(4, MemoryLayouts.JAVA_BYTE).withName("sin_addr"),
135 MemoryLayout.ofPaddingBits(64)) // pad to size of struct sockaddr
136 .withName("sockaddr_in"),
137 MemoryLayout.ofStruct(familyLayout,
138 MemoryLayout.ofValueBits(16, NETWORK_BYTE_ORDER).withName("sin6_port"),
139 MemoryLayout.ofValueBits(32, HOST_BYTE_ORDER).withName("sin6_flowinfo"),
140 //MemoryLayout.ofValueBits(128, NETWORK_BYTE_ORDER).withName("sin6_addr"), // #### treat as bits rather than bytes?
141 MemoryLayout.ofSequence(16, MemoryLayouts.JAVA_BYTE).withName("sin6_addr"),
142 MemoryLayout.ofValueBits(32, HOST_BYTE_ORDER).withName("sin6_scope_id"))
143 .withName("sockaddr_in6"))
144 .withName("sockaddr");
145
146 PathElement sockaddr_in = groupElement("sockaddr_in");
147 SIN_PORT_HANDLE = MemoryHandles.filterValue(
148 SOCKADDR.varHandle(short.class, sockaddr_in, groupElement("sin_port")),
149 INT_TO_SHORT,
150 SHORT_TO_UNSIGNED_INT);
151 SIN_ADDR_HANDLE = SOCKADDR.varHandle(byte.class, sockaddr_in, groupElement("sin_addr"), sequenceElement());
152 PathElement sockaddr_in6 = groupElement("sockaddr_in6");
153 SIN6_PORT_HANDLE = MemoryHandles.filterValue(
154 SOCKADDR.varHandle(short.class, sockaddr_in6, groupElement("sin6_port")),
155 INT_TO_SHORT,
156 SHORT_TO_UNSIGNED_INT);
157 SIN6_FLOWINFO_HANDLE = SOCKADDR.varHandle(int.class, sockaddr_in6, groupElement("sin6_flowinfo"));
158 SIN6_ADDR_HANDLE = SOCKADDR.varHandle(byte.class, sockaddr_in6, groupElement("sin6_addr"), sequenceElement());
159 SIN6_SCOPE_HANDLE = SOCKADDR.varHandle(int.class, sockaddr_in6, groupElement("sin6_scope_id"));
160
161 // byte-wise handle for equality comparison
162 MemoryLayout layout = MemoryLayout.ofSequence(SOCKADDR.byteSize(), MemoryLayouts.JAVA_BYTE);
163 BYTEWISE_HANDLE = layout.varHandle(byte.class, sequenceElement());
164
165 SOCKADDR_IN_SIZE = (int) SOCKADDR.select(sockaddr_in).byteSize();
166 SOCKADDR_IN6_SIZE = (int) SOCKADDR.select(sockaddr_in6).byteSize();
167
168 debug();
169 // Verifies the handcrafted layout against the natively derived sizes and offsets
170 if (VERIFY)
171 verify();
172 }
173
174 private static void verify() {
175 // sockaddr_in
176 PathElement sockaddr_in = groupElement("sockaddr_in");
177 assert SIZEOF_SOCKADDR4 == SOCKADDR_IN_SIZE : "SIZEOF_SOCKADDR [%d] != SOCKADDR_IN_SIZE [%d]".formatted(SIZEOF_SOCKADDR4, SOCKADDR_IN_SIZE);
178 var offset = bitsToBytes(SOCKADDR.offset(sockaddr_in , groupElement("sin_port")));
179 assert offset == OFFSET_SIN4_PORT : "OFFSET_SIN4_PORT [%d] != layout offset [%d]".formatted(OFFSET_SIN4_PORT, offset);
180 offset = bitsToBytes(SOCKADDR.offset(sockaddr_in , groupElement("sin_addr")));
181 assert offset == OFFSET_SIN4_ADDR : "OFFSET_SIN4_ADDR [%d] != layout offset [%d]".formatted(OFFSET_SIN4_ADDR, offset);
182
183 //sockaddr_in6
184 PathElement sockaddr_in6 = groupElement("sockaddr_in6");
185 assert SIZEOF_SOCKADDR6 == SOCKADDR_IN6_SIZE : "SIZEOF_SOCKADDR6 [%d] != SOCKADDR_IN6_SIZE [%d]".formatted(SIZEOF_SOCKADDR6, SOCKADDR_IN6_SIZE);
186 offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_port")));
187 assert offset == OFFSET_SIN6_PORT : "OFFSET_SIN6_PORT [%d] != layout offset [%d]".formatted(OFFSET_SIN6_PORT, offset);
188 offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_addr")));
189 assert offset == OFFSET_SIN6_ADDR : "OFFSET_SIN6_ADDR [%d] != layout offset [%d]".formatted(OFFSET_SIN6_ADDR, offset);
190 offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_flowinfo")));
191 assert offset == OFFSET_SIN6_FLOWINFO : "OFFSET_SIN6_FLOWINFO [%d] != layout offset [%d]".formatted(OFFSET_SIN6_FLOWINFO, offset);
192 offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_scope_id")));
193 assert offset == OFFSET_SIN6_SCOPE_ID : "OFFSET_SIN6_SCOPE_ID [%d] != layout offset [%d]".formatted(OFFSET_SIN6_SCOPE_ID, offset);
194 }
195
196 private static void debug() {
197 if (DEBUG) {
198 System.out.println("SIZEOF_SOCKADDR4:" + SIZEOF_SOCKADDR4);
199 System.out.println("SIZEOF_SOCKADDR6:" + SIZEOF_SOCKADDR6);
200 System.out.println("SIZEOF_SOCKETADDRESS:" + SIZEOF_SOCKETADDRESS);
201 System.out.println("SIZEOF_FAMILY:" + SIZEOF_FAMILY);
202 System.out.println("OFFSET_FAMILY:" + OFFSET_FAMILY);
203 System.out.println("OFFSET_SIN4_PORT:" + OFFSET_SIN4_PORT);
204 System.out.println("OFFSET_SIN4_ADDR:" + OFFSET_SIN4_ADDR);
205 System.out.println("OFFSET_SIN6_PORT:" + OFFSET_SIN6_PORT);
206 System.out.println("OFFSET_SIN6_ADDR:" + OFFSET_SIN6_ADDR);
207 System.out.println("OFFSET_SIN6_SCOPE_ID:" + OFFSET_SIN6_SCOPE_ID);
208 System.out.println("OFFSET_SIN6_FLOWINFO:" + OFFSET_SIN6_FLOWINFO);
209 System.out.println("SOCKADDR layout:" + SOCKADDR);
210 System.out.println("SOCKADDR layout byteSize:" + SOCKADDR.byteSize());
211 System.out.println("SOCKADDR layout byteAlignment:" + SOCKADDR.byteAlignment());
212 }
213 }
214
215 private static long bitsToBytes(long value) {
216 return value / 8;
217 }
218
219 private static byte byteValue(int value) {
220 return (byte)value;
221 }
222
223 private static short shortValue(int value) {
224 return (short)value;
225 }
226
227 private final MemorySegment segment;
228 private final MemoryAddress memoryAddress;
229 private final long rawAddress;
230
231 long address() {
232 return rawAddress;
233 }
234
235 NativeSocketAddress() {
236 var initialSegment = MemorySegment.allocateNative(SOCKADDR);
237 //segment = MemorySegment.ofNativeRestricted(initialSegment.baseAddress(), initialSegment.byteSize(), null, () -> initialSegment.close(), null); // TODO: cannot close from another thread!
238 segment = MemorySegment.ofNativeRestricted(initialSegment.baseAddress(), initialSegment.byteSize(), null, null, null);
239 memoryAddress = segment.baseAddress();
240 rawAddress = memoryAddress.toRawLongValue();
241 }
242
243 /**
244 * Allocate an array of native socket addresses.
245 */
246 static NativeSocketAddress[] allocate(int count) {
247 NativeSocketAddress[] array = new NativeSocketAddress[count];
248 for (int i = 0; i < count; i++) {
249 try {
250 array[i] = new NativeSocketAddress();
251 } catch (OutOfMemoryError e) {
252 freeAll(array);
253 throw e;
254 }
255 }
256 return array;
257 }
258
259 /**
260 * Free all non-null native socket addresses in the given array.
261 */
262 static void freeAll(NativeSocketAddress[] array) {
263 for (int i = 0; i < array.length; i++) {
264 NativeSocketAddress sa = array[i];
265 if (sa != null) {
266 sa.segment.close();
267 // #### underlying segment is not closed
268 }
269 }
270 }
271
272 /**
273 * Encodes the given InetSocketAddress into this socket address.
274 * @param protocolFamily protocol family
275 * @param isa the InetSocketAddress to encode
276 * @return the size of the socket address (sizeof sockaddr or sockaddr6)
277 * @throws UnsupportedAddressTypeException if the address type is not supported
278 */
279 int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {
280 if (protocolFamily == StandardProtocolFamily.INET) {
281 // struct sockaddr_in
282 InetAddress ia = isa.getAddress();
283 if (!(ia instanceof Inet4Address))
284 throw new UnsupportedAddressTypeException();
285 putFamily(AF_INET);
286 putAddress(AF_INET, ia);
287 putPort(AF_INET, isa.getPort());
288 return SOCKADDR_IN_SIZE;
289 } else {
290 // struct sockaddr_in6
291 putFamily(AF_INET6);
292 putAddress(AF_INET6, isa.getAddress());
293 putPort(AF_INET6, isa.getPort());
294 SIN6_FLOWINFO_HANDLE.set(memoryAddress, 0);
295 return SOCKADDR_IN6_SIZE;
296 }
297 }
298
299 /**
300 * Return an InetSocketAddress to represent the socket address in this buffer.
301 * @throws SocketException if the socket address is not AF_INET or AF_INET6
302 */
303 InetSocketAddress decode() throws SocketException {
304 int family = family();
305 if (family != AF_INET && family != AF_INET6)
306 throw new SocketException("Socket family not recognized");
307 return new InetSocketAddress(address(family), port(family));
308 }
309
310 @Override
311 public boolean equals(Object other) {
312 if (!(other instanceof NativeSocketAddress)) {
313 return false;
314 }
315 var that = (NativeSocketAddress)other;
316
317 // #### this is byte-at-a-time, do we need to compare with a larger stride?
318
319 final MemoryAddress thisAddress = this.memoryAddress;
320 final MemoryAddress thatAddress = that.memoryAddress;
321 for (int i = 0; i < SOCKADDR.byteSize(); i++) {
322 byte b1 = (byte) BYTEWISE_HANDLE.get(thisAddress, i);
323 byte b2 = (byte) BYTEWISE_HANDLE.get(thatAddress, i);
324 if (b1 != b2)
325 return false;
326 }
327 return true;
328 }
329
330 @Override
331 public int hashCode() {
332 int h = 0;
333 final MemoryAddress address = memoryAddress;
334 for (int i = 0; i < SOCKADDR.byteSize(); i++) {
335 h = 31 * h + (byte) BYTEWISE_HANDLE.get(address, i);
336 }
337 return h;
338 }
339
340 @Override
341 public String toString() {
342 int family = family();
343 if (family == AF_INET || family == AF_INET6) {
344 return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
345 + ", address=" + address(family) + ", port=" + port(family);
346 } else {
347 return "<unknown>";
348 }
349 }
350
351 /**
352 * Return the value of the sa_family field.
353 */
354 private int family() {
355 return (int) SA_FAMILY_HANDLE.get(memoryAddress);
356 }
357
358 /**
359 * Stores the given family in the sa_family field.
360 */
361 private void putFamily(int family) {
362 SA_FAMILY_HANDLE.set(memoryAddress, family);
363 }
364
365 /**
366 * Return the value of the sin_port or sin6_port field. These fields are
367 * stored in network order.
368 */
369 private int port(int family) {
370 if (family == AF_INET)
371 return (int) SIN_PORT_HANDLE.get(memoryAddress);
372 else
373 return (int) SIN6_PORT_HANDLE.get(memoryAddress);
374 }
375
376 /**
377 * Stores the given port number in the sin_port or sin6_port field. The
378 * port is stored in network order.
379 */
380 private void putPort(int family, int port) {
381 if (family == AF_INET)
382 SIN_PORT_HANDLE.set(memoryAddress, port);
383 else
384 SIN6_PORT_HANDLE.set(memoryAddress, port);
385 }
386
387 /**
388 * Return an InetAddress to represent the value of the address in the
389 * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is
390 * created with the sin6_scope_id in the sockaddr_in6 structure.
391 */
392 private InetAddress address(int family) {
393 final MemoryAddress address = memoryAddress;
394 int scope_id;
395 byte[] bytes;
396
397 if (family == AF_INET) {
398 bytes = new byte[4];
399 for (int i = 0; i < 4; i++)
400 bytes[i] = (byte) SIN_ADDR_HANDLE.get(address, i);
401 scope_id = 0;
402 } else {
403 bytes = new byte[16];
404 for (int i = 0; i < 16; i++)
405 bytes[i] = (byte) SIN6_ADDR_HANDLE.get(address, i);
406 scope_id = (int) SIN6_SCOPE_HANDLE.get(address);
407 }
408 try {
409 if (scope_id == 0) {
410 return InetAddress.getByAddress(bytes);
411 } else {
412 return Inet6Address.getByAddress(null, bytes, scope_id);
413 }
414 } catch (UnknownHostException e) {
415 throw new InternalError(e);
416 }
417 }
418
419 /**
420 * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id
421 * fields. For IPv6 addresses, the sin6_addr will be popluated with an
422 * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address.
423 */
424 private void putAddress(int family, InetAddress ia) {
425 final MemoryAddress address = memoryAddress;
426 if (family == AF_INET) {
427 // IPv4 address
428 putIPv4Address(address, (Inet4Address)ia);
429 } else {
430 int scope_id;
431 if (ia instanceof Inet4Address) {
432 // IPv4-mapped IPv6 address
433 putMappedAddress(address, (Inet4Address)ia);
434 scope_id = 0;
435 } else {
436 // IPv6 address
437 var inet6Address = (Inet6Address) ia;
438 putIPv6Address(address, inet6Address);
439 scope_id = inet6Address.getScopeId();
440 }
441 SIN6_SCOPE_HANDLE.set(address, scope_id);
442 }
443 }
444
445 private static void putIPv4Address(MemoryAddress address, Inet4Address ia) {
446 int ipAddress = JNINA.addressValue(ia);
447 SIN_ADDR_HANDLE.set(address, 0, (byte) ((ipAddress >>> 24) & 0xFF));
448 SIN_ADDR_HANDLE.set(address, 1, (byte) ((ipAddress >>> 16) & 0xFF));
449 SIN_ADDR_HANDLE.set(address, 2, (byte) ((ipAddress >>> 8) & 0xFF));
450 SIN_ADDR_HANDLE.set(address, 3, (byte) ((ipAddress >>> 0) & 0xFF));
451 }
452
453 private static void putMappedAddress(MemoryAddress address, Inet4Address ia) {
454 int ipAddress = JNINA.addressValue(ia);
455 for (int i=0; i< 10; i++)
456 SIN6_ADDR_HANDLE.set(address, i, (byte) 0x00);
457
458 SIN6_ADDR_HANDLE.set(address, 10, (byte) 0xFF);
459 SIN6_ADDR_HANDLE.set(address, 11, (byte) 0xFF);
460 SIN6_ADDR_HANDLE.set(address, 12, (byte) ((ipAddress >>> 24) & 0xFF));
461 SIN6_ADDR_HANDLE.set(address, 13, (byte) ((ipAddress >>> 16) & 0xFF));
462 SIN6_ADDR_HANDLE.set(address, 14, (byte) ((ipAddress >>> 8) & 0xFF));
463 SIN6_ADDR_HANDLE.set(address, 15, (byte) ((ipAddress >>> 0) & 0xFF));
464 }
465
466 private static void putIPv6Address(MemoryAddress address, Inet6Address ia) {
467 byte[] bytes = JNINA.addressBytes(ia);
468 for (int i = 0; i < 16; i++)
469 SIN6_ADDR_HANDLE.set(address, i, bytes[i]);
470 }
471
472 private static native int AFINET();
473 private static native int AFINET6();
474 private static native int sizeofSockAddr4();
475 private static native int sizeofSockAddr6();
476 private static native int sizeofFamily();
477 private static native int offsetFamily();
478 private static native int offsetSin4Port();
479 private static native int offsetSin4Addr();
480 private static native int offsetSin6Port();
481 private static native int offsetSin6Addr();
482 private static native int offsetSin6ScopeId();
483 private static native int offsetSin6FlowInfo();
484
485 static {
486 IOUtil.load();
487 }
488 }
|