Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/windows/native/libnio/ch/Net.c
41134 views
1
/*
2
* Copyright (c) 2001, 2021, 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
#include <windows.h>
27
#include <winsock2.h>
28
29
#include "jni.h"
30
#include "jni_util.h"
31
#include "jvm.h"
32
#include "jlong.h"
33
#include "nio.h"
34
#include "nio_util.h"
35
#include "net_util.h"
36
37
#include "sun_nio_ch_Net.h"
38
#include "sun_nio_ch_PollArrayWrapper.h"
39
40
/**
41
* Definitions to allow for building with older SDK include files.
42
*/
43
44
#ifndef MCAST_BLOCK_SOURCE
45
46
#define MCAST_BLOCK_SOURCE 43
47
#define MCAST_UNBLOCK_SOURCE 44
48
#define MCAST_JOIN_SOURCE_GROUP 45
49
#define MCAST_LEAVE_SOURCE_GROUP 46
50
51
#endif /* MCAST_BLOCK_SOURCE */
52
53
struct my_ip_mreq_source {
54
IN_ADDR imr_multiaddr;
55
IN_ADDR imr_sourceaddr;
56
IN_ADDR imr_interface;
57
};
58
59
struct my_group_source_req {
60
ULONG gsr_interface;
61
SOCKADDR_STORAGE gsr_group;
62
SOCKADDR_STORAGE gsr_source;
63
};
64
65
/**
66
* Copy IPv6 address as jbytearray to target
67
*/
68
#define COPY_INET6_ADDRESS(env, source, target) \
69
(*env)->GetByteArrayRegion(env, source, 0, 16, target)
70
71
/**
72
* Enable or disable receipt of WSAECONNRESET errors.
73
*/
74
static void setConnectionReset(SOCKET s, BOOL enable) {
75
DWORD bytesReturned = 0;
76
WSAIoctl(s, SIO_UDP_CONNRESET, &enable, sizeof(enable),
77
NULL, 0, &bytesReturned, NULL, NULL);
78
}
79
80
jint handleSocketError(JNIEnv *env, int errorValue)
81
{
82
NET_ThrowNew(env, errorValue, NULL);
83
return IOS_THROWN;
84
}
85
86
static jclass isa_class; /* java.net.InetSocketAddress */
87
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
88
89
JNIEXPORT void JNICALL
90
Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
91
{
92
jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
93
CHECK_NULL(cls);
94
isa_class = (*env)->NewGlobalRef(env, cls);
95
if (isa_class == NULL) {
96
JNU_ThrowOutOfMemoryError(env, NULL);
97
return;
98
}
99
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
100
CHECK_NULL(isa_ctorID);
101
102
initInetAddressIDs(env);
103
}
104
105
JNIEXPORT jboolean JNICALL
106
Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
107
{
108
/*
109
* Return true if IPv6 is configured
110
*/
111
return ipv6_available() ? JNI_TRUE : JNI_FALSE;
112
}
113
114
JNIEXPORT jboolean JNICALL
115
Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1)
116
{
117
// SO_REUSEPORT is not supported on Windows
118
return JNI_FALSE;
119
}
120
121
JNIEXPORT jint JNICALL
122
Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
123
return 1;
124
}
125
126
JNIEXPORT jboolean JNICALL
127
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
128
{
129
/* Set both IPv4 and IPv6 socket options when setting multicast options */
130
return JNI_TRUE;
131
}
132
133
JNIEXPORT jboolean JNICALL
134
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
135
{
136
/* IPv6 sockets can join IPv4 multicast groups */
137
return JNI_TRUE;
138
}
139
140
JNIEXPORT jboolean JNICALL
141
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
142
{
143
/* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */
144
return JNI_FALSE;
145
}
146
147
JNIEXPORT jboolean JNICALL
148
Java_sun_nio_ch_Net_canUseIPv6OptionsWithIPv4LocalAddress0(JNIEnv* env, jclass cl)
149
{
150
/* IPV6_XXX socket options cannot be used on IPv6 sockets bound to IPv4 address */
151
return JNI_FALSE;
152
}
153
154
JNIEXPORT jint JNICALL
155
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
156
jboolean stream, jboolean reuse, jboolean fastLoopback)
157
{
158
SOCKET s;
159
int domain = (preferIPv6) ? AF_INET6 : AF_INET;
160
161
s = socket(domain, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
162
if (s != INVALID_SOCKET) {
163
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
164
165
/* IPV6_V6ONLY is true by default */
166
if (domain == AF_INET6) {
167
int opt = 0;
168
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
169
(const char *)&opt, sizeof(opt));
170
}
171
172
/* Disable WSAECONNRESET errors for initially unconnected UDP sockets */
173
if (!stream) {
174
setConnectionReset(s, FALSE);
175
}
176
177
} else {
178
NET_ThrowNew(env, WSAGetLastError(), "socket");
179
}
180
181
if (stream && fastLoopback) {
182
static int loopback_available = 1;
183
if (loopback_available) {
184
int rv = NET_EnableFastTcpLoopback((jint)s);
185
if (rv) {
186
if (rv == WSAEOPNOTSUPP) {
187
loopback_available = 0;
188
} else {
189
NET_ThrowNew(env, rv, "fastLoopback");
190
}
191
}
192
}
193
}
194
195
return (jint)s;
196
}
197
198
JNIEXPORT void JNICALL
199
Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6,
200
jboolean isExclBind, jobject iao, jint port)
201
{
202
SOCKETADDRESS sa;
203
int rv;
204
int sa_len = 0;
205
206
if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
207
return;
208
}
209
210
rv = NET_WinBind(fdval(env, fdo), &sa, sa_len, isExclBind);
211
if (rv == SOCKET_ERROR)
212
NET_ThrowNew(env, WSAGetLastError(), "bind");
213
}
214
215
JNIEXPORT void JNICALL
216
Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
217
{
218
if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) {
219
NET_ThrowNew(env, WSAGetLastError(), "listen");
220
}
221
}
222
223
JNIEXPORT jint JNICALL
224
Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo,
225
jobject iao, jint port)
226
{
227
SOCKETADDRESS sa;
228
int rv;
229
int so_rv;
230
int sa_len = 0;
231
SOCKET s = (SOCKET)fdval(env, fdo);
232
int type = 0, optlen = sizeof(type);
233
234
if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
235
return IOS_THROWN;
236
}
237
238
so_rv = getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &optlen);
239
240
/**
241
* Windows has a very long socket connect timeout of 2 seconds.
242
* If it's the loopback adapter we can shorten the wait interval.
243
*/
244
if (so_rv == 0 && type == SOCK_STREAM && IS_LOOPBACK_ADDRESS(&sa)) {
245
NET_EnableFastTcpLoopbackConnect((jint)s);
246
}
247
248
rv = connect(s, &sa.sa, sa_len);
249
if (rv != 0) {
250
int err = WSAGetLastError();
251
if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) {
252
return IOS_UNAVAILABLE;
253
}
254
NET_ThrowNew(env, err, "connect");
255
return IOS_THROWN;
256
} else {
257
/* Enable WSAECONNRESET errors when a UDP socket is connected */
258
if (so_rv == 0 && type == SOCK_DGRAM) {
259
setConnectionReset(s, TRUE);
260
}
261
}
262
return 1;
263
}
264
265
JNIEXPORT jint JNICALL
266
Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
267
jobjectArray isaa)
268
{
269
jint fd = fdval(env,fdo);
270
jint newfd;
271
SOCKETADDRESS sa;
272
int addrlen = sizeof(sa);
273
jobject remote_ia;
274
jint remote_port = 0;
275
jobject isa;
276
277
memset((char *)&sa, 0, sizeof(sa));
278
newfd = (jint) accept(fd, &sa.sa, &addrlen);
279
if (newfd == INVALID_SOCKET) {
280
int theErr = (jint)WSAGetLastError();
281
if (theErr == WSAEWOULDBLOCK) {
282
return IOS_UNAVAILABLE;
283
}
284
JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
285
return IOS_THROWN;
286
}
287
288
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
289
setfdval(env, newfdo, newfd);
290
291
remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
292
CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
293
294
isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
295
CHECK_NULL_RETURN(isa, IOS_THROWN);
296
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
297
298
return 1;
299
}
300
301
JNIEXPORT jint JNICALL
302
Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
303
{
304
SOCKETADDRESS sa;
305
int sa_len = sizeof(sa);
306
307
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
308
int error = WSAGetLastError();
309
if (error == WSAEINVAL) {
310
return 0;
311
}
312
NET_ThrowNew(env, error, "getsockname");
313
return IOS_THROWN;
314
}
315
return NET_GetPortFromSockaddr(&sa);
316
}
317
318
JNIEXPORT jobject JNICALL
319
Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
320
{
321
SOCKETADDRESS sa;
322
int sa_len = sizeof(sa);
323
int port;
324
325
if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
326
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
327
return NULL;
328
}
329
return NET_SockaddrToInetAddress(env, &sa, &port);
330
}
331
332
JNIEXPORT jint JNICALL
333
Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
334
{
335
SOCKETADDRESS sa;
336
int sa_len = sizeof(sa);
337
338
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
339
int error = WSAGetLastError();
340
if (error == WSAEINVAL) {
341
return 0;
342
}
343
NET_ThrowNew(env, error, "getsockname");
344
return IOS_THROWN;
345
}
346
return NET_GetPortFromSockaddr(&sa);
347
}
348
349
JNIEXPORT jobject JNICALL
350
Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
351
{
352
SOCKETADDRESS sa;
353
int sa_len = sizeof(sa);
354
int port;
355
356
if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) == SOCKET_ERROR) {
357
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
358
return NULL;
359
}
360
return NET_SockaddrToInetAddress(env, &sa, &port);
361
}
362
363
JNIEXPORT jint JNICALL
364
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
365
jboolean mayNeedConversion, jint level, jint opt)
366
{
367
int result = 0;
368
struct linger linger;
369
char *arg;
370
int arglen, n;
371
372
if (level == SOL_SOCKET && opt == SO_LINGER) {
373
arg = (char *)&linger;
374
arglen = sizeof(linger);
375
} else {
376
arg = (char *)&result;
377
arglen = sizeof(result);
378
}
379
380
/**
381
* HACK: IP_TOS is deprecated on Windows and querying the option
382
* returns a protocol error. NET_GetSockOpt handles this and uses
383
* a fallback mechanism. Same applies to IPV6_TCLASS
384
*/
385
if ((level == IPPROTO_IP && opt == IP_TOS) || (level == IPPROTO_IPV6 && opt == IPV6_TCLASS)) {
386
mayNeedConversion = JNI_TRUE;
387
}
388
389
if (mayNeedConversion) {
390
n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
391
} else {
392
n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
393
}
394
if (n == SOCKET_ERROR) {
395
handleSocketError(env, WSAGetLastError());
396
return IOS_THROWN;
397
}
398
399
if (level == SOL_SOCKET && opt == SO_LINGER)
400
return linger.l_onoff ? linger.l_linger : -1;
401
else
402
return result;
403
}
404
405
JNIEXPORT void JNICALL
406
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
407
jboolean mayNeedConversion, jint level, jint opt, jint arg, jboolean ipv6)
408
{
409
struct linger linger;
410
char *parg;
411
int arglen, n;
412
413
if (level == SOL_SOCKET && opt == SO_LINGER) {
414
parg = (char *)&linger;
415
arglen = sizeof(linger);
416
if (arg >= 0) {
417
linger.l_onoff = 1;
418
linger.l_linger = (unsigned short)arg;
419
} else {
420
linger.l_onoff = 0;
421
linger.l_linger = 0;
422
}
423
} else {
424
parg = (char *)&arg;
425
arglen = sizeof(arg);
426
}
427
428
if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS) {
429
/* No op */
430
return;
431
}
432
433
if (mayNeedConversion) {
434
n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
435
} else {
436
n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
437
}
438
if (n == SOCKET_ERROR)
439
handleSocketError(env, WSAGetLastError());
440
}
441
442
JNIEXPORT jint JNICALL
443
Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
444
jint group, jint interf, jint source)
445
{
446
struct ip_mreq mreq;
447
struct my_ip_mreq_source mreq_source;
448
int opt, n, optlen;
449
void* optval;
450
451
if (source == 0) {
452
mreq.imr_multiaddr.s_addr = htonl(group);
453
mreq.imr_interface.s_addr = htonl(interf);
454
opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
455
optval = (void*)&mreq;
456
optlen = sizeof(mreq);
457
} else {
458
mreq_source.imr_multiaddr.s_addr = htonl(group);
459
mreq_source.imr_sourceaddr.s_addr = htonl(source);
460
mreq_source.imr_interface.s_addr = htonl(interf);
461
opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
462
optval = (void*)&mreq_source;
463
optlen = sizeof(mreq_source);
464
}
465
466
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
467
if (n == SOCKET_ERROR) {
468
if (join && (WSAGetLastError() == WSAENOPROTOOPT))
469
return IOS_UNAVAILABLE;
470
handleSocketError(env, WSAGetLastError());
471
}
472
return 0;
473
}
474
475
JNIEXPORT jint JNICALL
476
Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
477
jint group, jint interf, jint source)
478
{
479
struct my_ip_mreq_source mreq_source;
480
int n;
481
int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
482
483
mreq_source.imr_multiaddr.s_addr = htonl(group);
484
mreq_source.imr_sourceaddr.s_addr = htonl(source);
485
mreq_source.imr_interface.s_addr = htonl(interf);
486
487
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
488
(void*)&mreq_source, sizeof(mreq_source));
489
if (n == SOCKET_ERROR) {
490
if (block && (WSAGetLastError() == WSAENOPROTOOPT))
491
return IOS_UNAVAILABLE;
492
handleSocketError(env, WSAGetLastError());
493
}
494
return 0;
495
}
496
497
/**
498
* Call setsockopt with a IPPROTO_IPV6 level socket option
499
* and a group_source_req structure as the option value. The
500
* given IPv6 group, interface index, and IPv6 source address
501
* are copied into the structure.
502
*/
503
static int setGroupSourceReqOption(JNIEnv* env,
504
jobject fdo,
505
int opt,
506
jbyteArray group,
507
jint index,
508
jbyteArray source)
509
{
510
struct my_group_source_req req;
511
struct sockaddr_in6* sin6;
512
513
req.gsr_interface = (ULONG)index;
514
515
sin6 = (struct sockaddr_in6*)&(req.gsr_group);
516
sin6->sin6_family = AF_INET6;
517
COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
518
519
sin6 = (struct sockaddr_in6*)&(req.gsr_source);
520
sin6->sin6_family = AF_INET6;
521
COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
522
523
return setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req));
524
}
525
526
JNIEXPORT jint JNICALL
527
Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
528
jbyteArray group, jint index, jbyteArray source)
529
{
530
struct ipv6_mreq mreq6;
531
int n;
532
533
if (source == NULL) {
534
int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
535
COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
536
mreq6.ipv6mr_interface = (int)index;
537
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
538
(void*)&mreq6, sizeof(mreq6));
539
} else {
540
int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
541
n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
542
}
543
544
if (n == SOCKET_ERROR) {
545
handleSocketError(env, WSAGetLastError());
546
}
547
return 0;
548
}
549
550
JNIEXPORT jint JNICALL
551
Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
552
jbyteArray group, jint index, jbyteArray source)
553
{
554
int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
555
int n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
556
if (n == SOCKET_ERROR) {
557
handleSocketError(env, WSAGetLastError());
558
}
559
return 0;
560
}
561
562
JNIEXPORT void JNICALL
563
Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
564
{
565
struct in_addr in;
566
int arglen = sizeof(struct in_addr);
567
int n;
568
569
in.s_addr = htonl(interf);
570
571
n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
572
(void*)&(in.s_addr), arglen);
573
if (n == SOCKET_ERROR) {
574
handleSocketError(env, WSAGetLastError());
575
}
576
}
577
578
JNIEXPORT jint JNICALL
579
Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
580
{
581
struct in_addr in;
582
int arglen = sizeof(struct in_addr);
583
int n;
584
585
n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
586
if (n == SOCKET_ERROR) {
587
handleSocketError(env, WSAGetLastError());
588
return IOS_THROWN;
589
}
590
return ntohl(in.s_addr);
591
}
592
593
JNIEXPORT void JNICALL
594
Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
595
{
596
DWORD value = (jint)index;
597
int arglen = sizeof(value);
598
int n;
599
600
n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
601
(void*)&(index), arglen);
602
if (n == SOCKET_ERROR) {
603
handleSocketError(env, WSAGetLastError());
604
}
605
}
606
607
JNIEXPORT jint JNICALL
608
Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
609
{
610
DWORD index;
611
int arglen = sizeof(index);
612
int n;
613
614
n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
615
if (n == SOCKET_ERROR) {
616
handleSocketError(env, WSAGetLastError());
617
return -1;
618
}
619
return (jint)index;
620
}
621
622
JNIEXPORT void JNICALL
623
Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) {
624
int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SD_RECEIVE :
625
(jhow == sun_nio_ch_Net_SHUT_WR) ? SD_SEND : SD_BOTH;
626
if (shutdown(fdval(env, fdo), how) == SOCKET_ERROR) {
627
NET_ThrowNew(env, WSAGetLastError(), "shutdown");
628
}
629
}
630
631
JNIEXPORT jint JNICALL
632
Java_sun_nio_ch_Net_available(JNIEnv *env, jclass cl, jobject fdo)
633
{
634
int count = 0;
635
if (NET_SocketAvailable(fdval(env, fdo), &count) != 0) {
636
handleSocketError(env, WSAGetLastError());
637
return IOS_THROWN;
638
}
639
return (jint) count;
640
}
641
642
JNIEXPORT jint JNICALL
643
Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlong timeout)
644
{
645
int rv;
646
int revents = 0;
647
struct timeval t;
648
fd_set rd, wr, ex;
649
jint fd = fdval(env, fdo);
650
651
FD_ZERO(&rd);
652
FD_ZERO(&wr);
653
FD_ZERO(&ex);
654
if (events & POLLIN) {
655
FD_SET(fd, &rd);
656
}
657
if (events & POLLOUT) {
658
FD_SET(fd, &wr);
659
}
660
FD_SET(fd, &ex);
661
662
if (timeout >= 0) {
663
t.tv_sec = (long)(timeout / 1000);
664
t.tv_usec = (timeout % 1000) * 1000;
665
}
666
667
rv = select(fd+1, &rd, &wr, &ex, (timeout >= 0) ? &t : NULL);
668
669
/* save last winsock error */
670
if (rv == SOCKET_ERROR) {
671
handleSocketError(env, WSAGetLastError());
672
return IOS_THROWN;
673
} else if (rv >= 0) {
674
rv = 0;
675
if (FD_ISSET(fd, &rd)) {
676
rv |= POLLIN;
677
}
678
if (FD_ISSET(fd, &wr)) {
679
rv |= POLLOUT;
680
}
681
if (FD_ISSET(fd, &ex)) {
682
rv |= POLLERR;
683
}
684
}
685
return rv;
686
}
687
688
JNIEXPORT jboolean JNICALL
689
Java_sun_nio_ch_Net_pollConnect(JNIEnv* env, jclass this, jobject fdo, jlong timeout)
690
{
691
int optError = 0;
692
int result;
693
int n = sizeof(int);
694
jint fd = fdval(env, fdo);
695
fd_set wr, ex;
696
struct timeval t;
697
698
FD_ZERO(&wr);
699
FD_ZERO(&ex);
700
FD_SET((u_int)fd, &wr);
701
FD_SET((u_int)fd, &ex);
702
703
if (timeout >= 0) {
704
t.tv_sec = (long)(timeout / 1000);
705
t.tv_usec = (timeout % 1000) * 1000;
706
}
707
708
result = select(fd+1, 0, &wr, &ex, (timeout >= 0) ? &t : NULL);
709
710
if (result == SOCKET_ERROR) {
711
handleSocketError(env, WSAGetLastError());
712
return JNI_FALSE;
713
} else if (result == 0) {
714
return JNI_FALSE;
715
} else {
716
// connection established if writable and no error to check
717
if (FD_ISSET(fd, &wr) && !FD_ISSET(fd, &ex)) {
718
return JNI_TRUE;
719
}
720
result = getsockopt((SOCKET)fd,
721
SOL_SOCKET,
722
SO_ERROR,
723
(char *)&optError,
724
&n);
725
if (result == SOCKET_ERROR) {
726
int lastError = WSAGetLastError();
727
if (lastError != WSAEINPROGRESS) {
728
NET_ThrowNew(env, lastError, "getsockopt");
729
}
730
} else if (optError != NO_ERROR) {
731
handleSocketError(env, optError);
732
}
733
return JNI_FALSE;
734
}
735
}
736
737
JNIEXPORT jshort JNICALL
738
Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this)
739
{
740
return (jshort)POLLIN;
741
}
742
743
JNIEXPORT jshort JNICALL
744
Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this)
745
{
746
return (jshort)POLLOUT;
747
}
748
749
JNIEXPORT jshort JNICALL
750
Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this)
751
{
752
return (jshort)POLLERR;
753
}
754
755
JNIEXPORT jshort JNICALL
756
Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this)
757
{
758
return (jshort)POLLHUP;
759
}
760
761
JNIEXPORT jshort JNICALL
762
Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)
763
{
764
return (jshort)POLLNVAL;
765
}
766
767
JNIEXPORT jshort JNICALL
768
Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)
769
{
770
return (jshort)POLLOUT;
771
}
772
773
JNIEXPORT jint JNICALL
774
Java_sun_nio_ch_Net_sendOOB(JNIEnv* env, jclass this, jobject fdo, jbyte b)
775
{
776
int n = send(fdval(env, fdo), (const char*)&b, 1, MSG_OOB);
777
if (n == SOCKET_ERROR) {
778
if (WSAGetLastError() == WSAEWOULDBLOCK) {
779
return IOS_UNAVAILABLE;
780
} else {
781
JNU_ThrowIOExceptionWithLastError(env, "send failed");
782
return IOS_THROWN;
783
}
784
} else {
785
return n;
786
}
787
}
788
789
JNIEXPORT jboolean JNICALL
790
Java_sun_nio_ch_Net_discardOOB(JNIEnv* env, jclass clazz, jobject fdo)
791
{
792
char buf[8];
793
jboolean discarded = JNI_FALSE;
794
for (;;) {
795
int n = recv(fdval(env, fdo), (char*)&buf, sizeof(buf), MSG_OOB);
796
if (n == SOCKET_ERROR) {
797
if (WSAGetLastError() != WSAEWOULDBLOCK) {
798
JNU_ThrowIOExceptionWithLastError(env, "recv failed");
799
}
800
return discarded;
801
}
802
if (n <= 0)
803
return discarded;
804
if (n < (int)sizeof(buf))
805
return JNI_TRUE;
806
discarded = JNI_TRUE;
807
}
808
}
809
810