Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/java/net/DualStackPlainSocketImpl.c
32287 views
1
/*
2
* Copyright (c) 2007, 2013, 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
#include <windows.h>
26
#include <winsock2.h>
27
#include "jni.h"
28
#include "net_util.h"
29
#include "java_net_DualStackPlainSocketImpl.h"
30
31
#define SET_BLOCKING 0
32
#define SET_NONBLOCKING 1
33
34
static jclass isa_class; /* java.net.InetSocketAddress */
35
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
36
37
/*
38
* Class: java_net_DualStackPlainSocketImpl
39
* Method: initIDs
40
* Signature: ()V
41
*/
42
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
43
(JNIEnv *env, jclass clazz) {
44
45
jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
46
CHECK_NULL(cls);
47
isa_class = (*env)->NewGlobalRef(env, cls);
48
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
49
"(Ljava/net/InetAddress;I)V");
50
CHECK_NULL(isa_ctorID);
51
initInetAddressIDs(env);
52
53
// implement read timeout with select.
54
isRcvTimeoutSupported = 0;
55
}
56
57
/*
58
* Class: java_net_DualStackPlainSocketImpl
59
* Method: socket0
60
* Signature: (ZZ)I
61
*/
62
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
63
(JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
64
int fd, rv, opt=0;
65
66
fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
67
if (fd == INVALID_SOCKET) {
68
NET_ThrowNew(env, WSAGetLastError(), "create");
69
return -1;
70
}
71
72
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
73
if (rv == SOCKET_ERROR) {
74
NET_ThrowNew(env, WSAGetLastError(), "create");
75
}
76
77
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
78
79
return fd;
80
}
81
82
/*
83
* Class: java_net_DualStackPlainSocketImpl
84
* Method: bind0
85
* Signature: (ILjava/net/InetAddress;I)V
86
*/
87
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
88
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
89
jboolean exclBind)
90
{
91
SOCKETADDRESS sa;
92
int rv;
93
int sa_len = sizeof(sa);
94
95
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
96
&sa_len, JNI_TRUE) != 0) {
97
return;
98
}
99
100
rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
101
102
if (rv == SOCKET_ERROR)
103
NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind");
104
}
105
106
/*
107
* Class: java_net_DualStackPlainSocketImpl
108
* Method: connect0
109
* Signature: (ILjava/net/InetAddress;I)I
110
*/
111
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
112
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
113
SOCKETADDRESS sa;
114
int rv;
115
int sa_len = sizeof(sa);
116
117
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
118
&sa_len, JNI_TRUE) != 0) {
119
return -1;
120
}
121
122
rv = connect(fd, (struct sockaddr *)&sa, sa_len);
123
if (rv == SOCKET_ERROR) {
124
int err = WSAGetLastError();
125
if (err == WSAEWOULDBLOCK) {
126
return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
127
} else if (err == WSAEADDRNOTAVAIL) {
128
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
129
"connect: Address is invalid on local machine, or port is not valid on remote machine");
130
} else {
131
NET_ThrowNew(env, err, "connect");
132
}
133
return -1; // return value not important.
134
}
135
return rv;
136
}
137
138
/*
139
* Class: java_net_DualStackPlainSocketImpl
140
* Method: waitForConnect
141
* Signature: (II)V
142
*/
143
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
144
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
145
int rv, retry;
146
int optlen = sizeof(rv);
147
fd_set wr, ex;
148
struct timeval t;
149
150
FD_ZERO(&wr);
151
FD_ZERO(&ex);
152
FD_SET(fd, &wr);
153
FD_SET(fd, &ex);
154
t.tv_sec = timeout / 1000;
155
t.tv_usec = (timeout % 1000) * 1000;
156
157
/*
158
* Wait for timeout, connection established or
159
* connection failed.
160
*/
161
rv = select(fd+1, 0, &wr, &ex, &t);
162
163
/*
164
* Timeout before connection is established/failed so
165
* we throw exception and shutdown input/output to prevent
166
* socket from being used.
167
* The socket should be closed immediately by the caller.
168
*/
169
if (rv == 0) {
170
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
171
"connect timed out");
172
shutdown( fd, SD_BOTH );
173
return;
174
}
175
176
/*
177
* Socket is writable or error occurred. On some Windows editions
178
* the socket will appear writable when the connect fails so we
179
* check for error rather than writable.
180
*/
181
if (!FD_ISSET(fd, &ex)) {
182
return; /* connection established */
183
}
184
185
/*
186
* Connection failed. The logic here is designed to work around
187
* bug on Windows NT whereby using getsockopt to obtain the
188
* last error (SO_ERROR) indicates there is no error. The workaround
189
* on NT is to allow winsock to be scheduled and this is done by
190
* yielding and retrying. As yielding is problematic in heavy
191
* load conditions we attempt up to 3 times to get the error reason.
192
*/
193
for (retry=0; retry<3; retry++) {
194
NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
195
(char*)&rv, &optlen);
196
if (rv) {
197
break;
198
}
199
Sleep(0);
200
}
201
202
if (rv == 0) {
203
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
204
"Unable to establish connection");
205
} else {
206
NET_ThrowNew(env, rv, "connect");
207
}
208
}
209
210
/*
211
* Class: java_net_DualStackPlainSocketImpl
212
* Method: localPort0
213
* Signature: (I)I
214
*/
215
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
216
(JNIEnv *env, jclass clazz, jint fd) {
217
SOCKETADDRESS sa;
218
int len = sizeof(sa);
219
220
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
221
if (WSAGetLastError() == WSAENOTSOCK) {
222
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
223
"Socket closed");
224
} else {
225
NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
226
}
227
return -1;
228
}
229
return (int) ntohs((u_short)GET_PORT(&sa));
230
}
231
232
/*
233
* Class: java_net_DualStackPlainSocketImpl
234
* Method: localAddress
235
* Signature: (ILjava/net/InetAddressContainer;)V
236
*/
237
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
238
(JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
239
int port;
240
SOCKETADDRESS sa;
241
int len = sizeof(sa);
242
jobject iaObj;
243
jclass iaContainerClass;
244
jfieldID iaFieldID;
245
246
if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
247
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
248
return;
249
}
250
iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
251
CHECK_NULL(iaObj);
252
253
iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
254
iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
255
CHECK_NULL(iaFieldID);
256
(*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
257
}
258
259
260
/*
261
* Class: java_net_DualStackPlainSocketImpl
262
* Method: listen0
263
* Signature: (II)V
264
*/
265
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
266
(JNIEnv *env, jclass clazz, jint fd, jint backlog) {
267
if (listen(fd, backlog) == SOCKET_ERROR) {
268
NET_ThrowNew(env, WSAGetLastError(), "listen failed");
269
}
270
}
271
272
/*
273
* Class: java_net_DualStackPlainSocketImpl
274
* Method: accept0
275
* Signature: (I[Ljava/net/InetSocketAddress;)I
276
*/
277
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
278
(JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
279
int newfd, port=0;
280
jobject isa;
281
jobject ia;
282
SOCKETADDRESS sa;
283
int len = sizeof(sa);
284
285
memset((char *)&sa, 0, len);
286
newfd = accept(fd, (struct sockaddr *)&sa, &len);
287
288
if (newfd == INVALID_SOCKET) {
289
if (WSAGetLastError() == -2) {
290
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
291
"operation interrupted");
292
} else {
293
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
294
"socket closed");
295
}
296
return -1;
297
}
298
299
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
300
301
ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
302
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
303
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
304
305
return newfd;
306
}
307
308
/*
309
* Class: java_net_DualStackPlainSocketImpl
310
* Method: waitForNewConnection
311
* Signature: (II)V
312
*/
313
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnection
314
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
315
int rv;
316
317
rv = NET_Timeout(fd, timeout);
318
if (rv == 0) {
319
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
320
"Accept timed out");
321
} else if (rv == -1) {
322
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
323
} else if (rv == -2) {
324
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
325
"operation interrupted");
326
}
327
}
328
329
/*
330
* Class: java_net_DualStackPlainSocketImpl
331
* Method: available0
332
* Signature: (I)I
333
*/
334
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0
335
(JNIEnv *env, jclass clazz, jint fd) {
336
jint available = -1;
337
338
if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
339
NET_ThrowNew(env, WSAGetLastError(), "socket available");
340
}
341
342
return available;
343
}
344
345
/*
346
* Class: java_net_DualStackPlainSocketImpl
347
* Method: close0
348
* Signature: (I)V
349
*/
350
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0
351
(JNIEnv *env, jclass clazz, jint fd) {
352
NET_SocketClose(fd);
353
}
354
355
/*
356
* Class: java_net_DualStackPlainSocketImpl
357
* Method: shutdown0
358
* Signature: (II)V
359
*/
360
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
361
(JNIEnv *env, jclass clazz, jint fd, jint howto) {
362
shutdown(fd, howto);
363
}
364
365
366
/*
367
* Class: java_net_DualStackPlainSocketImpl
368
* Method: setIntOption
369
* Signature: (III)V
370
*/
371
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
372
(JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value) {
373
374
int level = 0, opt = 0;
375
struct linger linger = {0, 0};
376
char *parg;
377
int arglen;
378
379
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
380
JNU_ThrowByNameWithLastError(env,
381
JNU_JAVANETPKG "SocketException",
382
"Invalid option");
383
return;
384
}
385
386
if (opt == java_net_SocketOptions_SO_LINGER) {
387
parg = (char *)&linger;
388
arglen = sizeof(linger);
389
if (value >= 0) {
390
linger.l_onoff = 1;
391
linger.l_linger = (unsigned short)value;
392
} else {
393
linger.l_onoff = 0;
394
linger.l_linger = 0;
395
}
396
} else {
397
parg = (char *)&value;
398
arglen = sizeof(value);
399
}
400
401
if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
402
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
403
}
404
}
405
406
/*
407
* Class: java_net_DualStackPlainSocketImpl
408
* Method: getIntOption
409
* Signature: (II)I
410
*/
411
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
412
(JNIEnv *env, jclass clazz, jint fd, jint cmd) {
413
414
int level = 0, opt = 0;
415
int result=0;
416
struct linger linger = {0, 0};
417
char *arg;
418
int arglen;
419
420
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
421
JNU_ThrowByNameWithLastError(env,
422
JNU_JAVANETPKG "SocketException",
423
"Unsupported socket option");
424
return -1;
425
}
426
427
if (opt == java_net_SocketOptions_SO_LINGER) {
428
arg = (char *)&linger;
429
arglen = sizeof(linger);
430
} else {
431
arg = (char *)&result;
432
arglen = sizeof(result);
433
}
434
435
if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
436
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
437
return -1;
438
}
439
440
if (opt == java_net_SocketOptions_SO_LINGER)
441
return linger.l_onoff ? linger.l_linger : -1;
442
else
443
return result;
444
}
445
446
447
/*
448
* Class: java_net_DualStackPlainSocketImpl
449
* Method: sendOOB
450
* Signature: (II)V
451
*/
452
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB
453
(JNIEnv *env, jclass clazz, jint fd, jint data) {
454
jint n;
455
unsigned char d = (unsigned char) data & 0xff;
456
457
n = send(fd, (char *)&data, 1, MSG_OOB);
458
if (n == JVM_IO_ERR) {
459
NET_ThrowNew(env, WSAGetLastError(), "send");
460
} else if (n == JVM_IO_INTR) {
461
JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
462
}
463
}
464
465
/*
466
* Class: java_net_DualStackPlainSocketImpl
467
* Method: configureBlocking
468
* Signature: (IZ)V
469
*/
470
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking
471
(JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
472
u_long arg;
473
int result;
474
475
if (blocking == JNI_TRUE) {
476
arg = SET_BLOCKING; // 0
477
} else {
478
arg = SET_NONBLOCKING; // 1
479
}
480
481
result = ioctlsocket(fd, FIONBIO, &arg);
482
if (result == SOCKET_ERROR) {
483
NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
484
}
485
}
486
487