Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/nio/ch/sctp/SctpNet.c
32301 views
1
/*
2
* Copyright (c) 2009, 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
#include <stdlib.h>
27
#include <string.h>
28
#include <dlfcn.h>
29
30
#include "Sctp.h"
31
#include "jni.h"
32
#include "jni_util.h"
33
#include "nio_util.h"
34
#include "nio.h"
35
#include "net_util.h"
36
#include "net_util_md.h"
37
#include "sun_nio_ch_sctp_SctpNet.h"
38
#include "sun_nio_ch_sctp_SctpStdSocketOption.h"
39
40
static jclass isaCls = 0;
41
static jmethodID isaCtrID = 0;
42
43
static const char* nativeSctpLib = "libsctp.so.1";
44
static jboolean funcsLoaded = JNI_FALSE;
45
46
sctp_getladdrs_func* nio_sctp_getladdrs;
47
sctp_freeladdrs_func* nio_sctp_freeladdrs;
48
sctp_getpaddrs_func* nio_sctp_getpaddrs;
49
sctp_freepaddrs_func* nio_sctp_freepaddrs;
50
sctp_bindx_func* nio_sctp_bindx;
51
sctp_peeloff_func* nio_sctp_peeloff;
52
53
JNIEXPORT jint JNICALL JNI_OnLoad
54
(JavaVM *vm, void *reserved) {
55
return JNI_VERSION_1_2;
56
}
57
58
static int preCloseFD = -1; /* File descriptor to which we dup other fd's
59
before closing them for real */
60
61
/**
62
* Loads the native sctp library that contains the socket extension
63
* functions, as well as locating the individual functions.
64
* There will be a pending exception if this method returns false.
65
*/
66
jboolean loadSocketExtensionFuncs
67
(JNIEnv* env) {
68
if (dlopen(nativeSctpLib, RTLD_GLOBAL | RTLD_LAZY) == NULL) {
69
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
70
dlerror());
71
return JNI_FALSE;
72
}
73
74
if ((nio_sctp_getladdrs = (sctp_getladdrs_func*)
75
dlsym(RTLD_DEFAULT, "sctp_getladdrs")) == NULL) {
76
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
77
dlerror());
78
return JNI_FALSE;
79
}
80
81
if ((nio_sctp_freeladdrs = (sctp_freeladdrs_func*)
82
dlsym(RTLD_DEFAULT, "sctp_freeladdrs")) == NULL) {
83
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
84
dlerror());
85
return JNI_FALSE;
86
}
87
88
if ((nio_sctp_getpaddrs = (sctp_getpaddrs_func*)
89
dlsym(RTLD_DEFAULT, "sctp_getpaddrs")) == NULL) {
90
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
91
dlerror());
92
return JNI_FALSE;
93
}
94
95
if ((nio_sctp_freepaddrs = (sctp_freepaddrs_func*)
96
dlsym(RTLD_DEFAULT, "sctp_freepaddrs")) == NULL) {
97
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
98
dlerror());
99
return JNI_FALSE;
100
}
101
102
if ((nio_sctp_bindx = (sctp_bindx_func*)
103
dlsym(RTLD_DEFAULT, "sctp_bindx")) == NULL) {
104
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
105
dlerror());
106
return JNI_FALSE;
107
}
108
109
if ((nio_sctp_peeloff = (sctp_peeloff_func*)
110
dlsym(RTLD_DEFAULT, "sctp_peeloff")) == NULL) {
111
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
112
dlerror());
113
return JNI_FALSE;
114
}
115
116
funcsLoaded = JNI_TRUE;
117
return JNI_TRUE;
118
}
119
120
jint
121
handleSocketError(JNIEnv *env, jint errorValue)
122
{
123
char *xn;
124
switch (errorValue) {
125
case EINPROGRESS: /* Non-blocking connect */
126
return 0;
127
case EPROTO:
128
xn= JNU_JAVANETPKG "ProtocolException";
129
break;
130
case ECONNREFUSED:
131
xn = JNU_JAVANETPKG "ConnectException";
132
break;
133
case ETIMEDOUT:
134
xn = JNU_JAVANETPKG "ConnectException";
135
break;
136
case EHOSTUNREACH:
137
xn = JNU_JAVANETPKG "NoRouteToHostException";
138
break;
139
case EADDRINUSE: /* Fall through */
140
case EADDRNOTAVAIL:
141
xn = JNU_JAVANETPKG "BindException";
142
break;
143
default:
144
xn = JNU_JAVANETPKG "SocketException";
145
break;
146
}
147
errno = errorValue;
148
JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
149
return IOS_THROWN;
150
}
151
152
/*
153
* Class: sun_nio_ch_sctp_SctpNet
154
* Method: init
155
* Signature: ()V
156
*/
157
JNIEXPORT void JNICALL
158
Java_sun_nio_ch_sctp_SctpNet_init
159
(JNIEnv *env, jclass cl) {
160
int sp[2];
161
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
162
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
163
return;
164
}
165
preCloseFD = sp[0];
166
close(sp[1]);
167
initInetAddressIDs(env);
168
}
169
170
/*
171
* Class: sun_nio_ch_sctp_SctpNet
172
* Method: socket0
173
* Signature: (Z)I
174
*/
175
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpNet_socket0
176
(JNIEnv *env, jclass klass, jboolean oneToOne) {
177
int fd;
178
struct sctp_event_subscribe event;
179
#ifdef AF_INET6
180
int domain = ipv6_available() ? AF_INET6 : AF_INET;
181
#else
182
int domain = AF_INET;
183
#endif
184
185
/* Try to load the socket API extension functions */
186
if (!funcsLoaded && !loadSocketExtensionFuncs(env)) {
187
return 0;
188
}
189
190
fd = socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), IPPROTO_SCTP);
191
192
if (fd < 0) {
193
return handleSocketError(env, errno);
194
}
195
196
/* Enable events */
197
memset(&event, 0, sizeof(event));
198
event.sctp_data_io_event = 1;
199
event.sctp_association_event = 1;
200
event.sctp_address_event = 1;
201
event.sctp_send_failure_event = 1;
202
//event.sctp_peer_error_event = 1;
203
event.sctp_shutdown_event = 1;
204
//event.sctp_partial_delivery_event = 1;
205
//event.sctp_adaptation_layer_event = 1;
206
if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) {
207
handleSocketError(env, errno);
208
}
209
return fd;
210
}
211
212
/*
213
* Class: sun_nio_ch_sctp_SctpNet
214
* Method: bindx
215
* Signature: (I[Ljava/net/InetAddress;IIZ)V
216
*/
217
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_bindx
218
(JNIEnv *env, jclass klass, jint fd, jobjectArray addrs, jint port,
219
jint addrsLength, jboolean add, jboolean preferIPv6) {
220
SOCKADDR *sap, *tmpSap;
221
int i, sa_len = sizeof(SOCKADDR);
222
jobject ia;
223
224
if (addrsLength < 1)
225
return;
226
227
if ((sap = calloc(addrsLength, sa_len)) == NULL) {
228
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
229
return;
230
}
231
232
tmpSap = sap;
233
for (i=0; i<addrsLength; i++) {
234
ia = (*env)->GetObjectArrayElement(env, addrs, i);
235
if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr*)tmpSap,
236
&sa_len, preferIPv6) != 0) {
237
free(sap);
238
return;
239
}
240
tmpSap++;
241
}
242
243
if (nio_sctp_bindx(fd, (void*)sap, addrsLength, add ? SCTP_BINDX_ADD_ADDR :
244
SCTP_BINDX_REM_ADDR) != 0) {
245
handleSocketError(env, errno);
246
}
247
248
free(sap);
249
}
250
251
/*
252
* Class: sun_nio_ch_sctp_SctpNet
253
* Method: listen0
254
* Signature: (II)V
255
*/
256
JNIEXPORT void JNICALL
257
Java_sun_nio_ch_sctp_SctpNet_listen0
258
(JNIEnv *env, jclass cl, jint fd, jint backlog) {
259
if (listen(fd, backlog) < 0)
260
handleSocketError(env, errno);
261
}
262
263
/*
264
* Class: sun_nio_ch_sctp_SctpNet
265
* Method: connect0
266
* Signature: (ILjava/net/InetAddress;I)I
267
*/
268
JNIEXPORT jint JNICALL
269
Java_sun_nio_ch_sctp_SctpNet_connect0
270
(JNIEnv *env, jclass clazz, int fd, jobject iao, jint port) {
271
SOCKADDR sa;
272
int sa_len = SOCKADDR_LEN;
273
int rv;
274
275
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
276
&sa_len, JNI_TRUE) != 0) {
277
return IOS_THROWN;
278
}
279
280
rv = connect(fd, (struct sockaddr *)&sa, sa_len);
281
if (rv != 0) {
282
if (errno == EINPROGRESS) {
283
return IOS_UNAVAILABLE;
284
} else if (errno == EINTR) {
285
return IOS_INTERRUPTED;
286
}
287
return handleSocketError(env, errno);
288
}
289
return 1;
290
}
291
292
/*
293
* Class: sun_nio_ch_sctp_SctpNet
294
* Method: close0
295
* Signature: (I)V
296
*/
297
JNIEXPORT void JNICALL
298
Java_sun_nio_ch_sctp_SctpNet_close0
299
(JNIEnv *env, jclass clazz, jint fd) {
300
if (fd != -1) {
301
int rv = close(fd);
302
if (rv < 0)
303
JNU_ThrowIOExceptionWithLastError(env, "Close failed");
304
}
305
}
306
307
/*
308
* Class: sun_nio_ch_sctp_SctpNet
309
* Method: preClose0
310
* Signature: (I)V
311
*/
312
JNIEXPORT void JNICALL
313
Java_sun_nio_ch_sctp_SctpNet_preClose0
314
(JNIEnv *env, jclass clazz, jint fd) {
315
if (preCloseFD >= 0) {
316
if (dup2(preCloseFD, fd) < 0)
317
JNU_ThrowIOExceptionWithLastError(env, "dup2 failed");
318
}
319
}
320
321
void initializeISA
322
(JNIEnv* env) {
323
if (isaCls == 0) {
324
jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
325
CHECK_NULL(c);
326
isaCtrID = (*env)->GetMethodID(env, c, "<init>",
327
"(Ljava/net/InetAddress;I)V");
328
CHECK_NULL(isaCtrID);
329
isaCls = (*env)->NewGlobalRef(env, c);
330
CHECK_NULL(isaCls);
331
(*env)->DeleteLocalRef(env, c);
332
}
333
}
334
335
jobject SockAddrToInetSocketAddress
336
(JNIEnv *env, struct sockaddr* sap) {
337
int port = 0;
338
339
jobject ia = NET_SockaddrToInetAddress(env, sap, &port);
340
if (ia == NULL)
341
return NULL;
342
343
if (isaCls == 0) {
344
initializeISA(env);
345
CHECK_NULL_RETURN(isaCls, NULL);
346
}
347
348
return (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
349
}
350
351
/*
352
* Class: sun_nio_ch_sctp_SctpNet
353
* Method: getLocalAddresses0
354
* Signature: (I)[Ljava/net/SocketAddress;
355
*/
356
JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0
357
(JNIEnv *env, jclass klass, jint fd) {
358
void *addr_buf, *laddr;
359
struct sockaddr* sap;
360
int i, addrCount;
361
jobjectArray isaa;
362
363
#ifdef __solaris__
364
if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
365
#else /* __linux__ */
366
if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
367
#endif
368
handleSocketError(env, errno);
369
return NULL;
370
}
371
372
if (addrCount < 1)
373
return NULL;
374
375
if (isaCls == 0) {
376
initializeISA(env);
377
CHECK_NULL_RETURN(isaCls, NULL);
378
}
379
380
isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
381
if (isaa == NULL) {
382
nio_sctp_freeladdrs(addr_buf);
383
return NULL;
384
}
385
386
laddr = addr_buf;
387
for (i=0; i<addrCount; i++) {
388
int port = 0;
389
jobject isa = NULL, ia;
390
sap = (struct sockaddr*)addr_buf;
391
ia = NET_SockaddrToInetAddress(env, sap, &port);
392
if (ia != NULL)
393
isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
394
if (isa == NULL)
395
break;
396
(*env)->SetObjectArrayElement(env, isaa, i, isa);
397
398
if (sap->sa_family == AF_INET)
399
addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
400
else
401
addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
402
}
403
404
nio_sctp_freeladdrs(laddr);
405
return isaa;
406
}
407
408
jobjectArray getRemoteAddresses
409
(JNIEnv *env, jint fd, sctp_assoc_t id) {
410
void *addr_buf, *paddr;
411
struct sockaddr* sap;
412
int i, addrCount;
413
jobjectArray isaa;
414
415
#if __solaris__
416
if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
417
#else /* __linux__ */
418
if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) {
419
#endif
420
handleSocketError(env, errno);
421
return NULL;
422
}
423
424
if (addrCount < 1)
425
return NULL;
426
427
if (isaCls == 0) {
428
initializeISA(env);
429
CHECK_NULL_RETURN(isaCls, NULL);
430
}
431
432
isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
433
if (isaa == NULL) {
434
nio_sctp_freepaddrs(addr_buf);
435
return NULL;
436
}
437
438
paddr = addr_buf;
439
for (i=0; i<addrCount; i++) {
440
jobject ia, isa = NULL;
441
int port = 0;
442
sap = (struct sockaddr*)addr_buf;
443
ia = NET_SockaddrToInetAddress(env, sap, &port);
444
if (ia != NULL)
445
isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
446
if (isa == NULL)
447
break;
448
(*env)->SetObjectArrayElement(env, isaa, i, isa);
449
450
if (sap->sa_family == AF_INET)
451
addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
452
else
453
addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
454
}
455
456
nio_sctp_freepaddrs(paddr);
457
458
return isaa;
459
}
460
461
/*
462
* Class: sun_nio_ch_sctp_SctpNet
463
* Method: getRemoteAddresses0
464
* Signature: (II)[Ljava/net/SocketAddress;
465
*/
466
JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getRemoteAddresses0
467
(JNIEnv *env, jclass klass, jint fd, jint assocId) {
468
return getRemoteAddresses(env, fd, assocId);
469
}
470
471
/* Map the Java level option to the native level */
472
int mapSocketOption
473
(jint cmd, int *level, int *optname) {
474
static struct {
475
jint cmd;
476
int level;
477
int optname;
478
} const opts[] = {
479
{ sun_nio_ch_sctp_SctpStdSocketOption_SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS },
480
{ sun_nio_ch_sctp_SctpStdSocketOption_SCTP_EXPLICIT_COMPLETE, IPPROTO_SCTP, SCTP_EXPLICIT_EOR },
481
{ sun_nio_ch_sctp_SctpStdSocketOption_SCTP_FRAGMENT_INTERLEAVE, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE },
482
{ sun_nio_ch_sctp_SctpStdSocketOption_SCTP_NODELAY, IPPROTO_SCTP, SCTP_NODELAY },
483
{ sun_nio_ch_sctp_SctpStdSocketOption_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },
484
{ sun_nio_ch_sctp_SctpStdSocketOption_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },
485
{ sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER, SOL_SOCKET, SO_LINGER } };
486
487
int i;
488
for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
489
if (cmd == opts[i].cmd) {
490
*level = opts[i].level;
491
*optname = opts[i].optname;
492
return 0;
493
}
494
}
495
496
/* not found */
497
return -1;
498
}
499
500
/*
501
* Class: sun_nio_ch_sctp_SctpNet
502
* Method: setIntOption0
503
* Signature: (III)V
504
*/
505
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setIntOption0
506
(JNIEnv *env, jclass klass, jint fd, jint opt, int arg) {
507
int klevel, kopt;
508
int result;
509
struct linger linger;
510
void *parg;
511
int arglen;
512
513
if (mapSocketOption(opt, &klevel, &kopt) < 0) {
514
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
515
"Unsupported socket option");
516
return;
517
}
518
519
if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER) {
520
parg = (void *)&linger;
521
arglen = sizeof(linger);
522
if (arg >= 0) {
523
linger.l_onoff = 1;
524
linger.l_linger = arg;
525
} else {
526
linger.l_onoff = 0;
527
linger.l_linger = 0;
528
}
529
} else {
530
parg = (void *)&arg;
531
arglen = sizeof(arg);
532
}
533
534
if (NET_SetSockOpt(fd, klevel, kopt, parg, arglen) < 0) {
535
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
536
"sun_nio_ch_sctp_SctpNet.setIntOption0");
537
}
538
}
539
540
/*
541
* Class: sun_nio_ch_sctp_SctpNet
542
* Method: getIntOption0
543
* Signature: (II)I
544
*/
545
JNIEXPORT int JNICALL Java_sun_nio_ch_sctp_SctpNet_getIntOption0
546
(JNIEnv *env, jclass klass, jint fd, jint opt) {
547
int klevel, kopt;
548
int result;
549
struct linger linger;
550
void *arg;
551
int arglen;
552
553
memset((char *) &linger, 0, sizeof(linger));
554
if (mapSocketOption(opt, &klevel, &kopt) < 0) {
555
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
556
"Unsupported socket option");
557
return -1;
558
}
559
560
if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER) {
561
arg = (void *)&linger;
562
arglen = sizeof(linger);
563
} else {
564
arg = (void *)&result;
565
arglen = sizeof(result);
566
}
567
568
if (NET_GetSockOpt(fd, klevel, kopt, arg, &arglen) < 0) {
569
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
570
"sun.nio.ch.Net.getIntOption");
571
return -1;
572
}
573
574
if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER)
575
return linger.l_onoff ? linger.l_linger : -1;
576
else
577
return result;
578
}
579
580
/*
581
* Class: sun_nio_ch_sctp_SctpNet
582
* Method: getPrimAddrOption0
583
* Signature: (II)Ljava/net/SocketAddress;
584
*/
585
JNIEXPORT jobject JNICALL Java_sun_nio_ch_sctp_SctpNet_getPrimAddrOption0
586
(JNIEnv *env, jclass klass, jint fd, jint assocId) {
587
struct sctp_setprim prim;
588
unsigned int prim_len = sizeof(prim);
589
struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
590
591
prim.ssp_assoc_id = assocId;
592
593
if (getsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, &prim_len) < 0) {
594
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
595
"sun.nio.ch.SctpNet.getPrimAddrOption0");
596
return NULL;
597
}
598
599
return SockAddrToInetSocketAddress(env, sap);
600
}
601
602
/*
603
* Class: sun_nio_ch_sctp_SctpNet
604
* Method: setPrimAddrOption0
605
* Signature: (IILjava/net/InetAddress;I)V
606
*/
607
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPrimAddrOption0
608
(JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) {
609
struct sctp_setprim prim;
610
struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
611
int sap_len = sizeof(sap);
612
613
if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
614
&sap_len, JNI_TRUE) != 0) {
615
return;
616
}
617
618
prim.ssp_assoc_id = assocId;
619
620
if (setsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, sizeof(prim)) < 0) {
621
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
622
"sun.nio.ch.SctpNet.setPrimAddrOption0");
623
}
624
}
625
626
/*
627
* Class: sun_nio_ch_sctp_SctpNet
628
* Method: setPeerPrimAddrOption0
629
* Signature: (IILjava/net/InetAddress;I)V
630
*/
631
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPeerPrimAddrOption0
632
(JNIEnv *env, jclass klass, jint fd, jint assocId,
633
jobject iaObj, jint port, jboolean preferIPv6) {
634
struct sctp_setpeerprim prim;
635
struct sockaddr* sap = (struct sockaddr*)&prim.sspp_addr;
636
int sap_len = sizeof(sap);
637
638
if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
639
&sap_len, preferIPv6) != 0) {
640
return;
641
}
642
643
prim.sspp_assoc_id = assocId;
644
645
if (setsockopt(fd, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, &prim,
646
sizeof(prim)) < 0) {
647
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
648
"sun.nio.ch.SctpNet.setPeerPrimAddrOption0");
649
}
650
}
651
652
/*
653
* Class: sun_nio_ch_sctp_SctpNet
654
* Method: getInitMsgOption0
655
* Signature: (I[I)V
656
*/
657
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_getInitMsgOption0
658
(JNIEnv *env, jclass klass, jint fd, jintArray retVal) {
659
struct sctp_initmsg sctp_initmsg;
660
unsigned int sim_len = sizeof(sctp_initmsg);
661
int vals[2];
662
663
if (getsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_initmsg,
664
&sim_len) < 0) {
665
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
666
"sun.nio.ch.SctpNet.getInitMsgOption0");
667
return;
668
}
669
670
vals[0] = sctp_initmsg.sinit_max_instreams;
671
vals[1] = sctp_initmsg.sinit_num_ostreams;
672
(*env)->SetIntArrayRegion(env, retVal, 0, 2, vals);
673
}
674
675
/*
676
* Class: sun_nio_ch_sctp_SctpNet
677
* Method: setInitMsgOption0
678
* Signature: (III)V
679
*/
680
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setInitMsgOption0
681
(JNIEnv *env, jclass klass, jint fd, jint inArg, jint outArg) {
682
struct sctp_initmsg sctp_initmsg;
683
684
sctp_initmsg.sinit_max_instreams = (unsigned int)inArg;
685
sctp_initmsg.sinit_num_ostreams = (unsigned int)outArg;
686
sctp_initmsg.sinit_max_attempts = 0; // default
687
sctp_initmsg.sinit_max_init_timeo = 0; // default
688
689
if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_initmsg,
690
sizeof(sctp_initmsg)) < 0) {
691
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
692
"sun.nio.ch.SctpNet.setInitMsgOption0");
693
}
694
}
695
696
/*
697
* Class: sun_nio_ch_sctp_SctpNet
698
* Method: shutdown0
699
* Signature: (II)V
700
*/
701
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_shutdown0
702
(JNIEnv *env, jclass klass, jint fd, jint assocId) {
703
int rv;
704
struct msghdr msg[1];
705
struct iovec iov[1];
706
int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo));
707
char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
708
struct cmsghdr* cmsg;
709
struct sctp_sndrcvinfo *sri;
710
711
/* SctpSocketChannel */
712
if (assocId < 0) {
713
shutdown(fd, SHUT_WR);
714
return;
715
}
716
717
memset(msg, 0, sizeof (*msg));
718
memset(cbuf, 0, cbuf_size);
719
msg->msg_name = NULL;
720
msg->msg_namelen = 0;
721
iov->iov_base = NULL;
722
iov->iov_len = 0;
723
msg->msg_iov = iov;
724
msg->msg_iovlen = 1;
725
msg->msg_control = cbuf;
726
msg->msg_controllen = cbuf_size;
727
msg->msg_flags = 0;
728
729
cmsg = CMSG_FIRSTHDR(msg);
730
cmsg->cmsg_level = IPPROTO_SCTP;
731
cmsg->cmsg_type = SCTP_SNDRCV;
732
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
733
734
/* Initialize the payload: */
735
sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg);
736
memset(sri, 0, sizeof (*sri));
737
738
if (assocId > 0) {
739
sri->sinfo_assoc_id = assocId;
740
}
741
742
sri->sinfo_flags = sri->sinfo_flags | SCTP_EOF;
743
744
/* Sum of the length of all control messages in the buffer. */
745
msg->msg_controllen = cmsg->cmsg_len;
746
747
if ((rv = sendmsg(fd, msg, 0)) < 0) {
748
handleSocketError(env, errno);
749
}
750
}
751
752
/*
753
* Class: sun_nio_ch_sctp_SctpNet
754
* Method: branch
755
* Signature: (II)I
756
*/
757
JNIEXPORT int JNICALL Java_sun_nio_ch_sctp_SctpNet_branch0
758
(JNIEnv *env, jclass klass, jint fd, jint assocId) {
759
int newfd = 0;
760
if ((newfd = nio_sctp_peeloff(fd, assocId)) < 0) {
761
handleSocketError(env, errno);
762
}
763
764
return newfd;
765
}
766
767