Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java
41159 views
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
}
347
348